164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
61b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert*   Copyright (C) 1998-2015, International Business Machines
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* File parse.cpp
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date          Name          Description
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/26/99     stephen       Creation.
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   02/25/00     weiv          Overhaul to write udata
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   5/10/01      Ram           removed ustdio dependency
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/10/2001  Dominic Ludlam <dom@recoil.org> Rewritten
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Safer use of UnicodeString.
24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifndef UNISTR_FROM_CHAR_EXPLICIT
25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#   define UNISTR_FROM_CHAR_EXPLICIT explicit
26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Less important, but still a good idea.
29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifndef UNISTR_FROM_STRING_EXPLICIT
30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#   define UNISTR_FROM_STRING_EXPLICIT explicit
31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
33c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include <assert.h>
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "parse.h"
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "errmsg.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uhash.h"
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uinvchar.h"
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "read.h"
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr.h"
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "reslist.h"
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "rbt_pars.h"
4427f654740f2a26ad62a5c155af9199af9e69b889claireho#include "genrb.h"
45c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "unicode/stringpiece.h"
46c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "unicode/unistr.h"
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
4827f654740f2a26ad62a5c155af9199af9e69b889claireho#include "unicode/uscript.h"
49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utf16.h"
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
51c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "charstr.h"
52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationbuilder.h"
53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdata.h"
54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatareader.h"
55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatawriter.h"
56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationfastlatinbuilder.h"
57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationinfo.h"
58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationroot.h"
59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationruleparser.h"
60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationtailoring.h"
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Number of tokens to read ahead of the current stream position */
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MAX_LOOKAHEAD   3
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CR               0x000D
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LF               0x000A
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define SPACE            0x0020
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define TAB              0x0009
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ESCAPE           0x005C
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define HASH             0x0023
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define QUOTE            0x0027
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZERO             0x0030
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define STARTCOMMAND     0x005B
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ENDCOMMAND       0x005D
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define OPENSQBRACKET    0x005B
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CLOSESQBRACKET   0x005D
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
79c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::CharString;
80c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::LocalMemory;
81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliususing icu::LocalPointer;
82c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::LocalUCHARBUFPointer;
83c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::StringPiece;
84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliususing icu::UnicodeString;
85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct Lookahead
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     enum   ETokenType type;
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     struct UString    value;
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     struct UString    comment;
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     uint32_t          line;
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* keep in sync with token defines in read.h */
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *tokenNames[TOK_TOKEN_COUNT] =
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "string",             /* A string token, such as "MonthNames" */
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "'{'",                 /* An opening brace character */
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "'}'",                 /* A closing brace character */
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "','",                 /* A comma */
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "':'",                 /* A colon */
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "<end of file>",     /* End of the file has been reached successfully */
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "<end of line>"
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Just to store "TRUE" */
10854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const UChar trueValue[] = {0x0054, 0x0052, 0x0055, 0x0045, 0x0000};
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11027f654740f2a26ad62a5c155af9199af9e69b889clairehotypedef struct {
11127f654740f2a26ad62a5c155af9199af9e69b889claireho    struct Lookahead  lookahead[MAX_LOOKAHEAD + 1];
11227f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t          lookaheadPosition;
11327f654740f2a26ad62a5c155af9199af9e69b889claireho    UCHARBUF         *buffer;
11427f654740f2a26ad62a5c155af9199af9e69b889claireho    struct SRBRoot *bundle;
11527f654740f2a26ad62a5c155af9199af9e69b889claireho    const char     *inputdir;
11627f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t        inputdirLength;
11727f654740f2a26ad62a5c155af9199af9e69b889claireho    const char     *outputdir;
11827f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t        outputdirLength;
119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char     *filename;
120103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UBool           makeBinaryCollation;
12159d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool           omitCollationRules;
12227f654740f2a26ad62a5c155af9199af9e69b889claireho} ParseState;
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12427f654740f2a26ad62a5c155af9199af9e69b889clairehotypedef struct SResource *
12527f654740f2a26ad62a5c155af9199af9e69b889clairehoParseResourceFunction(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status);
12627f654740f2a26ad62a5c155af9199af9e69b889claireho
12727f654740f2a26ad62a5c155af9199af9e69b889clairehostatic struct SResource *parseResource(ParseState* state, char *tag, const struct UString *comment, UErrorCode *status);
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* The nature of the lookahead buffer:
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   There are MAX_LOOKAHEAD + 1 slots, used as a circular buffer.  This provides
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   MAX_LOOKAHEAD lookahead tokens and a slot for the current token and value.
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   When getToken is called, the current pointer is moved to the next slot and the
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   old slot is filled with the next token from the reader by calling getNextToken.
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   The token values are stored in the slot, which means that token values don't
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   survive a call to getToken, ie.
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   UString *value;
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   getToken(&value, NULL, status);
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   getToken(NULL,   NULL, status);       bad - value is now a different string
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
14327f654740f2a26ad62a5c155af9199af9e69b889clairehoinitLookahead(ParseState* state, UCHARBUF *buf, UErrorCode *status)
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static uint32_t initTypeStrings = 0;
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t i;
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!initTypeStrings)
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        initTypeStrings = 1;
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15327f654740f2a26ad62a5c155af9199af9e69b889claireho    state->lookaheadPosition   = 0;
15427f654740f2a26ad62a5c155af9199af9e69b889claireho    state->buffer              = buf;
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    resetLineNumber();
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < MAX_LOOKAHEAD; i++)
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
16027f654740f2a26ad62a5c155af9199af9e69b889claireho        state->lookahead[i].type = getNextToken(state->buffer, &state->lookahead[i].value, &state->lookahead[i].line, &state->lookahead[i].comment, status);
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_ZERO_ERROR;
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void
17127f654740f2a26ad62a5c155af9199af9e69b889clairehocleanupLookahead(ParseState* state)
172c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
173c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uint32_t i;
17454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    for (i = 0; i <= MAX_LOOKAHEAD; i++)
175c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
17627f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_deinit(&state->lookahead[i].value);
17727f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_deinit(&state->lookahead[i].comment);
178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
180c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
181c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic enum ETokenType
18327f654740f2a26ad62a5c155af9199af9e69b889clairehogetToken(ParseState* state, struct UString **tokenValue, struct UString* comment, uint32_t *linenumber, UErrorCode *status)
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum ETokenType result;
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          i;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
18827f654740f2a26ad62a5c155af9199af9e69b889claireho    result = state->lookahead[state->lookaheadPosition].type;
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tokenValue != NULL)
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
19227f654740f2a26ad62a5c155af9199af9e69b889claireho        *tokenValue = &state->lookahead[state->lookaheadPosition].value;
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (linenumber != NULL)
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
19727f654740f2a26ad62a5c155af9199af9e69b889claireho        *linenumber = state->lookahead[state->lookaheadPosition].line;
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (comment != NULL)
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
20227f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_cpy(comment, &(state->lookahead[state->lookaheadPosition].comment), status);
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20527f654740f2a26ad62a5c155af9199af9e69b889claireho    i = (state->lookaheadPosition + MAX_LOOKAHEAD) % (MAX_LOOKAHEAD + 1);
20627f654740f2a26ad62a5c155af9199af9e69b889claireho    state->lookaheadPosition = (state->lookaheadPosition + 1) % (MAX_LOOKAHEAD + 1);
20727f654740f2a26ad62a5c155af9199af9e69b889claireho    ustr_setlen(&state->lookahead[i].comment, 0, status);
20827f654740f2a26ad62a5c155af9199af9e69b889claireho    ustr_setlen(&state->lookahead[i].value, 0, status);
20927f654740f2a26ad62a5c155af9199af9e69b889claireho    state->lookahead[i].type = getNextToken(state->buffer, &state->lookahead[i].value, &state->lookahead[i].line, &state->lookahead[i].comment, status);
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* printf("getToken, returning %s\n", tokenNames[result]); */
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic enum ETokenType
21727f654740f2a26ad62a5c155af9199af9e69b889clairehopeekToken(ParseState* state, uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, struct UString *comment, UErrorCode *status)
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
21927f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t i = (state->lookaheadPosition + lookaheadCount) % (MAX_LOOKAHEAD + 1);
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TOK_ERROR;
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (lookaheadCount >= MAX_LOOKAHEAD)
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INTERNAL_PROGRAM_ERROR;
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TOK_ERROR;
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tokenValue != NULL)
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
23427f654740f2a26ad62a5c155af9199af9e69b889claireho        *tokenValue = &state->lookahead[i].value;
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (linenumber != NULL)
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
23927f654740f2a26ad62a5c155af9199af9e69b889claireho        *linenumber = state->lookahead[i].line;
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(comment != NULL){
24327f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_cpy(comment, &(state->lookahead[state->lookaheadPosition].comment), status);
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24627f654740f2a26ad62a5c155af9199af9e69b889claireho    return state->lookahead[i].type;
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
25027f654740f2a26ad62a5c155af9199af9e69b889clairehoexpect(ParseState* state, enum ETokenType expectedToken, struct UString **tokenValue, struct UString *comment, uint32_t *linenumber, UErrorCode *status)
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t        line;
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25427f654740f2a26ad62a5c155af9199af9e69b889claireho    enum ETokenType token = getToken(state, tokenValue, comment, &line, status);
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (linenumber != NULL)
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *linenumber = line;
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (token != expectedToken)
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "expecting %s, got %s", tokenNames[expectedToken], tokenNames[token]);
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    else
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_ZERO_ERROR;
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27727f654740f2a26ad62a5c155af9199af9e69b889clairehostatic char *getInvariantString(ParseState* state, uint32_t *line, struct UString *comment, UErrorCode *status)
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString *tokenValue;
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char           *result;
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t        count;
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
28327f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, comment, line, status);
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    count = u_strlen(tokenValue->fChars);
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!uprv_isInvariantUString(tokenValue->fChars, count)) {
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(*line, "invariant characters required for table keys, binary data, etc.");
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
29754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    result = static_cast<char *>(uprv_malloc(count+1));
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL)
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, result, count+1);
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
310103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusparseUCARules(ParseState* state, char *tag, uint32_t startline, const struct UString* /*comment*/, UErrorCode *status)
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FileStream       *file          = NULL;
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              filename[256] = { '\0' };
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              cs[128]       = { '\0' };
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool quoted = FALSE;
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCHARBUF *ucbuf=NULL;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32   c     = 0;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* cp  = NULL;
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *pTarget     = NULL;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *target      = NULL;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *targetLimit = NULL;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t size = 0;
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
32727f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* make the filename including the directory */
33827f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state->inputdir != NULL)
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
34027f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_strcat(filename, state->inputdir);
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34227f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(filename, U_FILE_SEP_STRING);
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35027f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(filename, cs);
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35859d709d503bab6e2b61931737e662dd293b40578ccornelius    if(state->omitCollationRules) {
359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return res_none();
360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf = ucbuf_open(filename, &cp, getShowWarning(),FALSE, status);
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status)) {
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "An error occured while opening the input file %s\n", filename);
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We allocate more space than actually required
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * since the actual size needed for storing UChars
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * is not known in UTF-8 byte stream
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size        = ucbuf_size(ucbuf) + 1;
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pTarget     = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * size);
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(pTarget, 0, size*U_SIZEOF_UCHAR);
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    target      = pTarget;
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    targetLimit = pTarget+size;
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* read the rules into the buffer */
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (target < targetLimit)
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        c = ucbuf_getc(ucbuf, status);
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(c == QUOTE) {
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            quoted = (UBool)!quoted;
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* weiv (06/26/2002): adding the following:
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * - preserving spaces in commands [...]
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * - # comments until the end of line
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (c == STARTCOMMAND && !quoted)
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* preserve commands
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * closing bracket will be handled by the
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * append at the end of the loop
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(c != ENDCOMMAND) {
39754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                U_APPEND_CHAR32_ONLY(c, target);
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c = ucbuf_getc(ucbuf, status);
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (c == HASH && !quoted) {
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* skip comments */
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(c != CR && c != LF) {
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c = ucbuf_getc(ucbuf, status);
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (c == ESCAPE)
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            c = unescape(ucbuf, status);
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
412103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (c == (UChar32)U_ERR)
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_free(pTarget);
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                T_FileStream_close(file);
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (!quoted && (c == SPACE || c == TAB || c == CR || c == LF))
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* ignore spaces carriage returns
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            * and line feed unless in the form \uXXXX
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            */
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Append UChar * after dissembling if c > 0xffff*/
428103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (c != (UChar32)U_EOF)
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
43054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            U_APPEND_CHAR32_ONLY(c, target);
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* terminate the string */
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(target < targetLimit){
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *target = 0x0000;
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44327f654740f2a26ad62a5c155af9199af9e69b889claireho    result = string_open(state->bundle, tag, pTarget, (int32_t)(target - pTarget), NULL, status);
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf_close(ucbuf);
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(pTarget);
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_FileStream_close(file);
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
454103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusparseTransliterator(ParseState* state, char *tag, uint32_t startline, const struct UString* /*comment*/, UErrorCode *status)
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FileStream       *file          = NULL;
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              filename[256] = { '\0' };
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              cs[128]       = { '\0' };
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCHARBUF *ucbuf=NULL;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* cp  = NULL;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *pTarget     = NULL;
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *pSource     = NULL;
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t size = 0;
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46827f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* make the filename including the directory */
47927f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state->inputdir != NULL)
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
48127f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_strcat(filename, state->inputdir);
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48327f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(filename, U_FILE_SEP_STRING);
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49127f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(filename, cs);
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf = ucbuf_open(filename, &cp, getShowWarning(),FALSE, status);
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status)) {
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "An error occured while opening the input file %s\n", filename);
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We allocate more space than actually required
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * since the actual size needed for storing UChars
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * is not known in UTF-8 byte stream
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pSource = ucbuf_getBuffer(ucbuf, &size, status);
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pTarget     = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * (size + 1));
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(pTarget, 0, size*U_SIZEOF_UCHAR);
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_TRANSLITERATION
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size = utrans_stripRules(pSource, size, pTarget, status);
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size = 0;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fprintf(stderr, " Warning: writing empty transliteration data ( UCONFIG_NO_TRANSLITERATION ) \n");
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
52127f654740f2a26ad62a5c155af9199af9e69b889claireho    result = string_open(state->bundle, tag, pTarget, size, NULL, status);
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf_close(ucbuf);
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(pTarget);
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_FileStream_close(file);
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
529c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic ArrayResource* dependencyArray = NULL;
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
53227f654740f2a26ad62a5c155af9199af9e69b889clairehoparseDependency(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *elem = NULL;
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              filename[256] = { '\0' };
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              cs[128]       = { '\0' };
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54127f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* make the filename including the directory */
55227f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state->outputdir != NULL)
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
55427f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_strcat(filename, state->outputdir);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55627f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->outputdir[state->outputdirLength - 1] != U_FILE_SEP_CHAR)
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(filename, U_FILE_SEP_STRING);
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(filename, cs);
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!T_FileStream_file_exists(filename)){
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isStrict()){
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "The dependency file %s does not exist. Please make sure it exists.\n",filename);
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }else{
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            warning(line, "The dependency file %s does not exist. Please make sure it exists.\n",filename);
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(dependencyArray==NULL){
57727f654740f2a26ad62a5c155af9199af9e69b889claireho        dependencyArray = array_open(state->bundle, "%%DEPENDENCY", NULL, status);
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(tag!=NULL){
58027f654740f2a26ad62a5c155af9199af9e69b889claireho        result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
58227f654740f2a26ad62a5c155af9199af9e69b889claireho    elem = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, comment, status);
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
584c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    dependencyArray->add(elem);
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
59027f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
59427f654740f2a26ad62a5c155af9199af9e69b889clairehoparseString(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*    if (tag != NULL && uprv_strcmp(tag, "%%UCARULES") == 0)
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return parseUCARules(tag, startline, status);
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }*/
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" string %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
60627f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, NULL, status);
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(*status))
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        doesn't survive expect either) */
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
61327f654740f2a26ad62a5c155af9199af9e69b889claireho        result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_SUCCESS(*status) && result) {
61527f654740f2a26ad62a5c155af9199af9e69b889claireho            expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
617c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (U_FAILURE(*status))
618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            {
619c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
620c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return NULL;
621c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
62927f654740f2a26ad62a5c155af9199af9e69b889clairehoparseAlias(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result  = NULL;
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
63427f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, NULL, status);
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" alias %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(*status))
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        doesn't survive expect either) */
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64527f654740f2a26ad62a5c155af9199af9e69b889claireho        result = alias_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64727f654740f2a26ad62a5c155af9199af9e69b889claireho        expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
651c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
659fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_COLLATION
660fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
661fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusnamespace {
66227f654740f2a26ad62a5c155af9199af9e69b889claireho
66327f654740f2a26ad62a5c155af9199af9e69b889clairehostatic struct SResource* resLookup(struct SResource* res, const char* key){
664c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (res == res_none() || !res->isTable()) {
66527f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
66627f654740f2a26ad62a5c155af9199af9e69b889claireho    }
66727f654740f2a26ad62a5c155af9199af9e69b889claireho
668c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource *list = static_cast<TableResource *>(res);
669c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    SResource *current = list->fFirst;
67027f654740f2a26ad62a5c155af9199af9e69b889claireho    while (current != NULL) {
67127f654740f2a26ad62a5c155af9199af9e69b889claireho        if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), key) == 0) {
67227f654740f2a26ad62a5c155af9199af9e69b889claireho            return current;
67327f654740f2a26ad62a5c155af9199af9e69b889claireho        }
67427f654740f2a26ad62a5c155af9199af9e69b889claireho        current = current->fNext;
67527f654740f2a26ad62a5c155af9199af9e69b889claireho    }
67627f654740f2a26ad62a5c155af9199af9e69b889claireho    return NULL;
67727f654740f2a26ad62a5c155af9199af9e69b889claireho}
67827f654740f2a26ad62a5c155af9199af9e69b889claireho
679fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass GenrbImporter : public icu::CollationRuleParser::Importer {
680fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic:
681fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    GenrbImporter(const char *in, const char *out) : inputDir(in), outputDir(out) {}
682fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    virtual ~GenrbImporter();
683f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    virtual void getRules(
684fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            const char *localeID, const char *collationType,
685f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            UnicodeString &rules,
686fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            const char *&errorReason, UErrorCode &errorCode);
687fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
688fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate:
689fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char *inputDir;
690fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char *outputDir;
691fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius};
692fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
693fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusGenrbImporter::~GenrbImporter() {}
694fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
695f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid
696fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusGenrbImporter::getRules(
697fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const char *localeID, const char *collationType,
698f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        UnicodeString &rules,
699fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const char *& /*errorReason*/, UErrorCode &errorCode) {
700c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString filename(localeID, errorCode);
701c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    for(int32_t i = 0; i < filename.length(); i++){
70227f654740f2a26ad62a5c155af9199af9e69b889claireho        if(filename[i] == '-'){
703c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            filename.data()[i] = '_';
70427f654740f2a26ad62a5c155af9199af9e69b889claireho        }
70527f654740f2a26ad62a5c155af9199af9e69b889claireho    }
706c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    filename.append(".txt", errorCode);
707fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(errorCode)) {
708f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
70927f654740f2a26ad62a5c155af9199af9e69b889claireho    }
710c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString inputDirBuf;
711c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString openFileName;
712fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(inputDir == NULL) {
713c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        const char *filenameBegin = uprv_strrchr(filename.data(), U_FILE_SEP_CHAR);
71427f654740f2a26ad62a5c155af9199af9e69b889claireho        if (filenameBegin != NULL) {
71527f654740f2a26ad62a5c155af9199af9e69b889claireho            /*
71627f654740f2a26ad62a5c155af9199af9e69b889claireho             * When a filename ../../../data/root.txt is specified,
71727f654740f2a26ad62a5c155af9199af9e69b889claireho             * we presume that the input directory is ../../../data
71827f654740f2a26ad62a5c155af9199af9e69b889claireho             * This is very important when the resource file includes
71927f654740f2a26ad62a5c155af9199af9e69b889claireho             * another file, like UCARules.txt or thaidict.brk.
72027f654740f2a26ad62a5c155af9199af9e69b889claireho             */
721c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            StringPiece dir = filename.toStringPiece();
722c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            const char *filenameLimit = filename.data() + filename.length();
723c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            dir.remove_suffix((int32_t)(filenameLimit - filenameBegin));
724c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            inputDirBuf.append(dir, errorCode);
725c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            inputDir = inputDirBuf.data();
72627f654740f2a26ad62a5c155af9199af9e69b889claireho        }
72727f654740f2a26ad62a5c155af9199af9e69b889claireho    }else{
728c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        int32_t dirlen  = (int32_t)uprv_strlen(inputDir);
72927f654740f2a26ad62a5c155af9199af9e69b889claireho
730c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if((filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')) {
73127f654740f2a26ad62a5c155af9199af9e69b889claireho            /*
73227f654740f2a26ad62a5c155af9199af9e69b889claireho             * append the input dir to openFileName if the first char in
733c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert             * filename is not file separator char and the last char input directory is  not '.'.
73427f654740f2a26ad62a5c155af9199af9e69b889claireho             * This is to support :
73527f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. /home/icu/data
73627f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. icu/data
73727f654740f2a26ad62a5c155af9199af9e69b889claireho             * The user cannot mix notations like
73827f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. /icu/data --- the absolute path specified. -s redundant
73927f654740f2a26ad62a5c155af9199af9e69b889claireho             * user should use
74027f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. icu/data  --- start from CWD and look in icu/data dir
74127f654740f2a26ad62a5c155af9199af9e69b889claireho             */
742c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            openFileName.append(inputDir, dirlen, errorCode);
743c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
744c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                openFileName.append(U_FILE_SEP_CHAR, errorCode);
74527f654740f2a26ad62a5c155af9199af9e69b889claireho            }
74627f654740f2a26ad62a5c155af9199af9e69b889claireho        }
74727f654740f2a26ad62a5c155af9199af9e69b889claireho    }
748c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    openFileName.append(filename, errorCode);
749c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if(U_FAILURE(errorCode)) {
750c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
751c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
752c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // printf("GenrbImporter::getRules(%s, %s) reads %s\n", localeID, collationType, openFileName.data());
753c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    const char* cp = "";
754c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalUCHARBUFPointer ucbuf(
755c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            ucbuf_open(openFileName.data(), &cp, getShowWarning(), TRUE, &errorCode));
756fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(errorCode == U_FILE_ACCESS_ERROR) {
757c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fprintf(stderr, "couldn't open file %s\n", openFileName.data());
758c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
75927f654740f2a26ad62a5c155af9199af9e69b889claireho    }
760c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (ucbuf.isNull() || U_FAILURE(errorCode)) {
761c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName.data(), u_errorName(errorCode));
762c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
76327f654740f2a26ad62a5c155af9199af9e69b889claireho    }
76427f654740f2a26ad62a5c155af9199af9e69b889claireho
76527f654740f2a26ad62a5c155af9199af9e69b889claireho    /* Parse the data into an SRBRoot */
766c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    struct SRBRoot *data =
767c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            parse(ucbuf.getAlias(), inputDir, outputDir, filename.data(), FALSE, FALSE, &errorCode);
768f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(errorCode)) {
769c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
770f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
77127f654740f2a26ad62a5c155af9199af9e69b889claireho
772c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    struct SResource *root = data->fRoot;
773c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    struct SResource *collations = resLookup(root, "collations");
774103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (collations != NULL) {
775c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert      struct SResource *collation = resLookup(collations, collationType);
776103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      if (collation != NULL) {
777c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        struct SResource *sequence = resLookup(collation, "Sequence");
778c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (sequence != NULL && sequence->isString()) {
779f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius          // No string pointer aliasing so that we need not hold onto the resource bundle.
780c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert          StringResource *sr = static_cast<StringResource *>(sequence);
781c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert          rules = sr->fString;
782103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
783103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      }
784103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
78527f654740f2a26ad62a5c155af9199af9e69b889claireho}
78627f654740f2a26ad62a5c155af9199af9e69b889claireho
787103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Quick-and-dirty escaping function.
788103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Assumes that we are on an ASCII-based platform.
789103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic void
790103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusescape(const UChar *s, char *buffer) {
791103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t length = u_strlen(s);
792103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t i = 0;
793103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    for (;;) {
794103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UChar32 c;
795103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U16_NEXT(s, i, length, c);
796103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (c == 0) {
797103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            *buffer = 0;
798103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return;
799103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else if (0x20 <= c && c <= 0x7e) {
800103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            // printable ASCII
801103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            *buffer++ = (char)c;  // assumes ASCII-based platform
802103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else {
803103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            buffer += sprintf(buffer, "\\u%04X", (int)c);
804103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
805103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
806103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
807103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
808fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}  // namespace
809fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
810fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif  // !UCONFIG_NO_COLLATION
811fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
812c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic TableResource *
813c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertaddCollation(ParseState* state, TableResource  *result, const char *collationType,
814fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             uint32_t startline, UErrorCode *status)
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
816fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // TODO: Use LocalPointer for result, or make caller close it when there is a failure.
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString     comment;
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType  token;
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char               subtag[1024];
822fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeString      rules;
823fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UBool              haveRules = FALSE;
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UVersionInfo       version;
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           line;
826fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . (name resource)* '}' */
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    version[0]=0; version[1]=0; version[2]=0; version[3]=0;
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_init(&comment);
83327f654740f2a26ad62a5c155af9199af9e69b889claireho        token = getToken(state, &tokenValue, &comment, &line, status);
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
837fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token != TOK_STRING)
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
842c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token == TOK_EOF)
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(startline, "unterminated table");
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(line, "Unexpected token %s", tokenNames[token]);
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
861c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
86527f654740f2a26ad62a5c155af9199af9e69b889claireho        member = parseResource(state, subtag, NULL, status);
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
869c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
872fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (result == NULL)
873fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        {
874fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Ignore the parsed resources, continue parsing.
875fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
876c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else if (uprv_strcmp(subtag, "Version") == 0 && member->isString())
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
878c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            StringResource *sr = static_cast<StringResource *>(member);
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char     ver[40];
880c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            int32_t length = sr->length();
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
882c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            if (length >= UPRV_LENGTHOF(ver))
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
884c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                length = UPRV_LENGTHOF(ver) - 1;
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
887c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            sr->fString.extract(0, length, ver, UPRV_LENGTHOF(ver), US_INV);
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_versionFromString(version, ver);
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
890c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            result->add(member, line, *status);
891fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            member = NULL;
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if(uprv_strcmp(subtag, "%%CollationBin")==0)
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* discard duplicate %%CollationBin if any*/
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
897c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else if (uprv_strcmp(subtag, "Sequence") == 0 && member->isString())
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
899c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            StringResource *sr = static_cast<StringResource *>(member);
900c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            rules = sr->fString;
901fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            haveRules = TRUE;
902fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Defer building the collator until we have seen
903fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // all sub-elements of the collation table, including the Version.
90450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* in order to achieve smaller data files, we can direct genrb */
90550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* to omit collation rules */
906fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(!state->omitCollationRules) {
907c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                result->add(member, line, *status);
908fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                member = NULL;
90950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
911fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        else  // Just copy non-special items.
912fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        {
913c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            result->add(member, line, *status);
914fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            member = NULL;
915fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
916fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(member);  // TODO: use LocalPointer
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
919c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
924fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (!haveRules) { return result; }
925fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
926fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if UCONFIG_NO_COLLATION || UCONFIG_NO_FILE_IO
927fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    warning(line, "Not building collation elements because of UCONFIG_NO_COLLATION and/or UCONFIG_NO_FILE_IO, see uconfig.h");
928fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    (void)collationType;
929fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#else
930f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // CLDR ticket #3949, ICU ticket #8082:
931f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Do not build collation binary data for for-import-only "private" collation rule strings.
932f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (uprv_strncmp(collationType, "private-", 8) == 0) {
933f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if(isVerbose()) {
934f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            printf("Not building %s~%s collation binary\n", state->filename, collationType);
935f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
936f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return result;
937f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
938f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
939fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(!state->makeBinaryCollation) {
940fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(isVerbose()) {
941fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            printf("Not building %s~%s collation binary\n", state->filename, collationType);
942fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
943fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return result;
944fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
945fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UErrorCode intStatus = U_ZERO_ERROR;
946fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UParseError parseError;
947fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uprv_memset(&parseError, 0, sizeof(parseError));
948fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    GenrbImporter importer(state->inputdir, state->outputdir);
949fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const icu::CollationTailoring *base = icu::CollationRoot::getRoot(intStatus);
950fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(intStatus)) {
951fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        error(line, "failed to load root collator (ucadata.icu) - %s", u_errorName(intStatus));
952fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
953fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;  // TODO: use LocalUResourceBundlePointer for result
954fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
955fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    icu::CollationBuilder builder(base, intStatus);
956fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(uprv_strncmp(collationType, "search", 6) == 0) {
957fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        builder.disableFastLatin();  // build fast-Latin table unless search collator
958fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
959fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    LocalPointer<icu::CollationTailoring> t(
960fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            builder.parseAndBuild(rules, version, &importer, &parseError, intStatus));
961fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(intStatus)) {
962fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const char *reason = builder.getErrorReason();
963fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(reason == NULL) { reason = ""; }
964fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        error(line, "CollationBuilder failed at %s~%s/Sequence rule offset %ld: %s  %s",
965fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                state->filename, collationType,
966fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                (long)parseError.offset, u_errorName(intStatus), reason);
967fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(parseError.preContext[0] != 0 || parseError.postContext[0] != 0) {
968fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Print pre- and post-context.
969fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            char preBuffer[100], postBuffer[100];
970fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            escape(parseError.preContext, preBuffer);
971fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            escape(parseError.postContext, postBuffer);
972fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            error(line, "  error context: \"...%s\" ! \"%s...\"", preBuffer, postBuffer);
973fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
974c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if(isStrict() || t.isNull()) {
975fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status = intStatus;
976fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            res_close(result);
977fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return NULL;
978fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
979fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
980fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    icu::LocalMemory<uint8_t> buffer;
981fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t capacity = 100000;
982fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uint8_t *dest = buffer.allocateInsteadAndCopy(capacity);
983fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(dest == NULL) {
984fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        fprintf(stderr, "memory allocation (%ld bytes) for file contents failed\n",
985fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                (long)capacity);
986fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_MEMORY_ALLOCATION_ERROR;
987fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
988fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
989fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
990fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t indexes[icu::CollationDataReader::IX_TOTAL_SIZE + 1];
991fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t totalSize = icu::CollationDataWriter::writeTailoring(
992fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *t, *t->settings, indexes, dest, capacity, intStatus);
993fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(intStatus == U_BUFFER_OVERFLOW_ERROR) {
994fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        intStatus = U_ZERO_ERROR;
995fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        capacity = totalSize;
996fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        dest = buffer.allocateInsteadAndCopy(capacity);
997fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(dest == NULL) {
998fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            fprintf(stderr, "memory allocation (%ld bytes) for file contents failed\n",
999fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    (long)capacity);
1000fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status = U_MEMORY_ALLOCATION_ERROR;
1001fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            res_close(result);
1002fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return NULL;
1003fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1004fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        totalSize = icu::CollationDataWriter::writeTailoring(
1005fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                *t, *t->settings, indexes, dest, capacity, intStatus);
1006fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1007fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(intStatus)) {
1008fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        fprintf(stderr, "CollationDataWriter::writeTailoring() failed: %s\n",
1009fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                u_errorName(intStatus));
1010fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
1011fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
1012fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1013fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(isVerbose()) {
1014fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        printf("%s~%s collation tailoring part sizes:\n", state->filename, collationType);
1015fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        icu::CollationInfo::printSizes(totalSize, indexes);
10161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        if(t->settings->hasReordering()) {
10171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            printf("%s~%s collation reordering ranges:\n", state->filename, collationType);
10181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            icu::CollationInfo::printReorderRanges(
10191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                    *t->data, t->settings->reorderCodes, t->settings->reorderCodesLength);
10201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        }
1021fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1022fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", totalSize, dest, NULL, NULL, status);
1023c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    result->add(collationBin, line, *status);
1024fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(*status)) {
1025fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
1026fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
1027fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1028fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
1029fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return result;
1030fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1031fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1032fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool
1033d9fc98087b091be81a9a50fbff9c0e22855d8dacFredrik RoubertkeepCollationType(const char *type) {  // android-changed
1034d9fc98087b091be81a9a50fbff9c0e22855d8dacFredrik Roubert    // BEGIN android-added
1035d9fc98087b091be81a9a50fbff9c0e22855d8dacFredrik Roubert    if (uprv_strcmp(type, "big5han") == 0) { return FALSE; }
1036d9fc98087b091be81a9a50fbff9c0e22855d8dacFredrik Roubert    if (uprv_strcmp(type, "gb2312han") == 0) { return FALSE; }
1037d9fc98087b091be81a9a50fbff9c0e22855d8dacFredrik Roubert    // END android-added
1038f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TRUE;
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
104227f654740f2a26ad62a5c155af9199af9e69b889clairehoparseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool newCollation, UErrorCode *status)
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1044c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource  *result = NULL;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString     comment;
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType  token;
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char               subtag[1024], typeKeyword[1024];
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           line;
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
105227f654740f2a26ad62a5c155af9199af9e69b889claireho    result = table_open(state->bundle, tag, NULL, status);
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" collation elements %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!newCollation) {
1062fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return addCollation(state, result, "(no type)", startline, status);
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ustr_init(&comment);
106727f654740f2a26ad62a5c155af9199af9e69b889claireho            token = getToken(state, &tokenValue, &comment, &line, status);
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token == TOK_CLOSE_BRACE)
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return result;
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token != TOK_STRING)
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1076c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INVALID_FORMAT_ERROR;
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (token == TOK_EOF)
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    error(startline, "unterminated table");
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                else
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    error(line, "Unexpected token %s", tokenNames[token]);
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(*status))
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1095c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (uprv_strcmp(subtag, "default") == 0)
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
110127f654740f2a26ad62a5c155af9199af9e69b889claireho                member = parseResource(state, subtag, NULL, status);
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(*status))
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1105c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    res_close(result);
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return NULL;
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1109c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                result->add(member, line, *status);
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
111327f654740f2a26ad62a5c155af9199af9e69b889claireho                token = peekToken(state, 0, &tokenValue, &line, &comment, status);
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* this probably needs to be refactored or recursively use the parser */
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* first we assume that our collation table won't have the explicit type */
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* then, we cannot handle aliases */
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(token == TOK_OPEN_BRACE) {
111827f654740f2a26ad62a5c155af9199af9e69b889claireho                    token = getToken(state, &tokenValue, &comment, &line, status);
1119c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                    TableResource *collationRes;
1120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (keepCollationType(subtag)) {
1121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        collationRes = table_open(state->bundle, subtag, NULL, status);
1122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
1123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        collationRes = NULL;
1124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
1125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // need to parse the collation data regardless
1126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    collationRes = addCollation(state, collationRes, subtag, startline, status);
1127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (collationRes != NULL) {
1128c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                        result->add(collationRes, startline, *status);
112927f654740f2a26ad62a5c155af9199af9e69b889claireho                    }
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else if(token == TOK_COLON) { /* right now, we'll just try to see if we have aliases */
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* we could have a table too */
113227f654740f2a26ad62a5c155af9199af9e69b889claireho                    token = peekToken(state, 1, &tokenValue, &line, &comment, status);
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    u_UCharsToChars(tokenValue->fChars, typeKeyword, u_strlen(tokenValue->fChars) + 1);
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(uprv_strcmp(typeKeyword, "alias") == 0) {
113527f654740f2a26ad62a5c155af9199af9e69b889claireho                        member = parseResource(state, subtag, NULL, status);
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (U_FAILURE(*status))
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        {
1138c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                            res_close(result);
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            return NULL;
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1142c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                        result->add(member, line, *status);
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
1144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        res_close(result);
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        *status = U_INVALID_FORMAT_ERROR;
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        return NULL;
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
1149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    res_close(result);
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *status = U_INVALID_FORMAT_ERROR;
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return NULL;
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);*/
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(*status))
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1161c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Necessary, because CollationElements requires the bundle->fRoot member to be present which,
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   if this weren't special-cased, wouldn't be set until the entire file had been processed. */
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
1171c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertrealParseTable(ParseState* state, TableResource *table, char *tag, uint32_t startline, UErrorCode *status)
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue=NULL;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    comment;
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType token;
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              subtag[1024];
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool             readToken = FALSE;
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . (name resource)* '}' */
1182103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" parsing table %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline);
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_init(&comment);
118927f654740f2a26ad62a5c155af9199af9e69b889claireho        token = getToken(state, &tokenValue, &comment, &line, status);
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!readToken) {
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                warning(startline, "Encountered empty table");
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return table;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token != TOK_STRING)
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token == TOK_EOF)
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(startline, "unterminated table");
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(line, "unexpected token %s", tokenNames[token]);
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(uprv_isInvariantUString(tokenValue->fChars, -1)) {
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "invariant characters required for table keys");
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            error(line, "parse error. Stopped parsing tokens with %s", u_errorName(*status));
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
122927f654740f2a26ad62a5c155af9199af9e69b889claireho        member = parseResource(state, subtag, &comment, status);
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (member == NULL || U_FAILURE(*status))
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            error(line, "parse error. Stopped parsing resource with %s", u_errorName(*status));
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1237c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        table->add(member, line, *status);
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            error(line, "parse error. Stopped parsing table with %s", u_errorName(*status));
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        readToken = TRUE;
1245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ustr_deinit(&comment);
1246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius   }
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* not reached */
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* A compiler warning will appear if all paths don't contain a return statement. */
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*     *status = U_INTERNAL_PROGRAM_ERROR;
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     return NULL;*/
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
125527f654740f2a26ad62a5c155af9199af9e69b889clairehoparseTable(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0)
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
125927f654740f2a26ad62a5c155af9199af9e69b889claireho        return parseCollationElements(state, tag, startline, FALSE, status);
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tag != NULL && uprv_strcmp(tag, "collations") == 0)
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
126327f654740f2a26ad62a5c155af9199af9e69b889claireho        return parseCollationElements(state, tag, startline, TRUE, status);
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" table %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1269c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource *result = table_open(state->bundle, tag, comment, status);
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
127527f654740f2a26ad62a5c155af9199af9e69b889claireho    return realParseTable(state, result, tag, startline,  status);
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
127927f654740f2a26ad62a5c155af9199af9e69b889clairehoparseArray(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    memberComments;
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType token;
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool             readToken = FALSE;
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1287c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    ArrayResource  *result = array_open(state->bundle, tag, comment, status);
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" array %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&memberComments);
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . resource [','] '}' */
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* reset length */
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_setlen(&memberComments, 0, status);
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* check for end of array, but don't consume next token unless it really is the end */
130627f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, &tokenValue, NULL, &memberComments, status);
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
131127f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!readToken) {
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                warning(startline, "Encountered empty array");
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_EOF)
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(startline, "unterminated array");
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* string arrays are a special case */
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_STRING)
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
132927f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, &tokenValue, &memberComments, NULL, status);
133027f654740f2a26ad62a5c155af9199af9e69b889claireho            member = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, &memberComments, status);
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
133427f654740f2a26ad62a5c155af9199af9e69b889claireho            member = parseResource(state, NULL, &memberComments, status);
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (member == NULL || U_FAILURE(*status))
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1343c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        result->add(member);
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* eat optional comma if present */
134627f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, NULL, NULL, NULL, status);
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_COMMA)
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
135027f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        readToken = TRUE;
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ustr_deinit(&memberComments);
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
136627f654740f2a26ad62a5c155af9199af9e69b889clairehoparseIntVector(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType  token;
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              *string;
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t            value;
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool              readToken = FALSE;
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              *stopstring;
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           len;
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString     memberComments;
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1376c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    IntVectorResource *result = intvector_open(state->bundle, tag, comment, status);
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" vector %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&memberComments);
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . string [','] '}' */
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_setlen(&memberComments, 0, status);
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* check for end of array, but don't consume next token unless it really is the end */
139327f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, NULL, NULL,&memberComments, status);
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* it's the end, consume the close brace */
139827f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!readToken) {
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                warning(startline, "Encountered empty int vector");
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1402c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ustr_deinit(&memberComments);
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return result;
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
140627f654740f2a26ad62a5c155af9199af9e69b889claireho        string = getInvariantString(state, NULL, NULL, status);
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* For handling illegal char in the Intvector */
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        value = uprv_strtoul(string, &stopstring, 0);/* make intvector support decimal,hexdigit,octal digit ranging from -2^31-2^32-1*/
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        len=(uint32_t)(stopstring-string);
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(len==uprv_strlen(string))
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1420c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            result->add(value, *status);
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(string);
142227f654740f2a26ad62a5c155af9199af9e69b889claireho            token = peekToken(state, 0, NULL, NULL, NULL, status);
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(string);
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_INVALID_CHAR_FOUND;
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the comma is optional (even though it is required to prevent the reader from concatenating
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        consecutive entries) so that a missing comma on the last entry isn't an error */
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_COMMA)
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
144027f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        readToken = TRUE;
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* not reached */
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* A compiler warning will appear if all paths don't contain a return statement. */
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*    intvector_close(result, status);
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_INTERNAL_PROGRAM_ERROR;
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;*/
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
145327f654740f2a26ad62a5c155af9199af9e69b889clairehoparseBinary(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1455c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    uint32_t line;
1456c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<char> string(getInvariantString(state, &line, NULL, status));
1457c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (string.isNull() || U_FAILURE(*status))
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146227f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" binary %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1472c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    uint32_t count = (uint32_t)uprv_strlen(string.getAlias());
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (count > 0){
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((count % 2)==0){
1475c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            LocalMemory<uint8_t> value;
1476c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            if (value.allocateInsteadAndCopy(count) == NULL)
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_MEMORY_ALLOCATION_ERROR;
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1482c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            char toConv[3] = {'\0', '\0', '\0'};
1483c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            for (uint32_t i = 0; i < count; i += 2)
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                toConv[0] = string[i];
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                toConv[1] = string[i + 1];
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1488c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                char *stopstring;
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16);
1490c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                uint32_t len=(uint32_t)(stopstring-toConv);
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1492c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                if(len!=2)
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *status=U_INVALID_CHAR_FOUND;
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return NULL;
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1499c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            return bin_open(state->bundle, tag, count >> 1, value.getAlias(), NULL, comment, status);
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_CHAR_FOUND;
1504c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            error(line, "Encountered invalid binary value (length is odd)");
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1510c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        warning(startline, "Encountered empty binary value");
1511c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return bin_open(state->bundle, tag, 0, NULL, "", comment, status);
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
151627f654740f2a26ad62a5c155af9199af9e69b889clairehoparseInteger(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t           value;
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char             *string;
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char             *stopstring;
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          len;
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152427f654740f2a26ad62a5c155af9199af9e69b889claireho    string = getInvariantString(state, NULL, NULL, status);
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (string == NULL || U_FAILURE(*status))
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
153127f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(string);
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" integer %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (uprv_strlen(string) <= 0)
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        warning(startline, "Encountered empty integer. Default value is 0.");
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* Allow integer support for hexdecimal, octal digit and decimal*/
1549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* and handle illegal char in the integer*/
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    value = uprv_strtoul(string, &stopstring, 0);
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    len=(uint32_t)(stopstring-string);
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(len==uprv_strlen(string))
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
155427f654740f2a26ad62a5c155af9199af9e69b889claireho        result = int_open(state->bundle, tag, value, comment, status);
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status=U_INVALID_CHAR_FOUND;
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(string);
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
156627f654740f2a26ad62a5c155af9199af9e69b889clairehoparseImport(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
1569c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<char> filename(getInvariantString(state, &line, NULL, status));
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
157527f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" import %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Open the input file for reading */
1587c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString fullname;
1588c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (state->inputdir != NULL) {
1589c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fullname.append(state->inputdir, *status);
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1591c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fullname.appendPathPart(filename.getAlias(), *status);
1592c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (U_FAILURE(*status)) {
1593c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return NULL;
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1596c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    FileStream *file = T_FileStream_open(fullname.data(), "rb");
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (file == NULL)
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1599c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        error(line, "couldn't open input file %s", filename.getAlias());
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_FILE_ACCESS_ERROR;
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1604c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    int32_t len  = T_FileStream_size(file);
1605c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<uint8_t> data;
1606c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if(data.allocateInsteadAndCopy(len) == NULL)
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        T_FileStream_close (file);
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1613c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /* int32_t numRead = */ T_FileStream_read(file, data.getAlias(), len);
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_FileStream_close (file);
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1616c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return bin_open(state->bundle, tag, len, data.getAlias(), fullname.data(), comment, status);
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
162027f654740f2a26ad62a5c155af9199af9e69b889clairehoparseInclude(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result;
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t           len=0;
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char             *filename;
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *pTarget     = NULL;
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCHARBUF *ucbuf;
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char     *fullname = NULL;
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  count     = 0;
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* cp = NULL;
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* uBuffer = NULL;
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
163427f654740f2a26ad62a5c155af9199af9e69b889claireho    filename = getInvariantString(state, &line, NULL, status);
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    count     = (int32_t)uprv_strlen(filename);
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
164227f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(filename);
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" include %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165427f654740f2a26ad62a5c155af9199af9e69b889claireho    fullname = (char *) uprv_malloc(state->inputdirLength + count + 2);
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* test for NULL */
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fullname == NULL)
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(filename);
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166327f654740f2a26ad62a5c155af9199af9e69b889claireho    if(state->inputdir!=NULL){
166427f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166727f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_strcpy(fullname, state->inputdir);
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166927f654740f2a26ad62a5c155af9199af9e69b889claireho            fullname[state->inputdirLength]      = U_FILE_SEP_CHAR;
167027f654740f2a26ad62a5c155af9199af9e69b889claireho            fullname[state->inputdirLength + 1] = '\0';
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(fullname, filename);
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
167627f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_strcpy(fullname, state->inputdir);
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(fullname, filename);
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }else{
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcpy(fullname,filename);
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf = ucbuf_open(fullname, &cp,getShowWarning(),FALSE,status);
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status)) {
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "couldn't open input file %s\n", filename);
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uBuffer = ucbuf_getBuffer(ucbuf,&len,status);
169127f654740f2a26ad62a5c155af9199af9e69b889claireho    result = string_open(state->bundle, tag, uBuffer, len, comment, status);
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
169354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    ucbuf_close(ucbuf);
169454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(pTarget);
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(filename);
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(fullname);
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_string,    "string",    6);
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_binary,    "binary",    6);
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_bin,       "bin",       3);
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_table,     "table",     5);
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_table_no_fallback,     "table(nofallback)",         17);
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_int,       "int",       3);
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_integer,   "integer",   7);
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_array,     "array",     5);
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_alias,     "alias",     5);
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_intvector, "intvector", 9);
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_import,    "import",    6);
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_include,   "include",   7);
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Various non-standard processing plugins that create one or more special resources. */
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_uca_rules,      "process(uca_rules)",        18);
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_collation,      "process(collation)",        18);
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_transliterator, "process(transliterator)",   23);
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_dependency,     "process(dependency)",       19);
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef enum EResourceType
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1728fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_UNKNOWN,
1729fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_STRING,
1730fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_BINARY,
1731fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_TABLE,
1732fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_TABLE_NO_FALLBACK,
1733fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_INTEGER,
1734fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_ARRAY,
1735fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_ALIAS,
1736fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_INTVECTOR,
1737fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_IMPORT,
1738fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_INCLUDE,
1739fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_UCA_RULES,
1740fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_COLLATION,
1741fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_TRANSLITERATOR,
1742fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_DEPENDENCY,
1743fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_RESERVED
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} EResourceType;
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct {
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *nameChars;   /* only used for debugging */
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *nameUChars;
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ParseResourceFunction *parseFunction;
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} gResourceTypes[] = {
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"Unknown", NULL, NULL},
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"string", k_type_string, parseString},
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"binary", k_type_binary, parseBinary},
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"table", k_type_table, parseTable},
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"table(nofallback)", k_type_table_no_fallback, NULL}, /* parseFunction will never be called */
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"integer", k_type_integer, parseInteger},
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"array", k_type_array, parseArray},
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"alias", k_type_alias, parseAlias},
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"intvector", k_type_intvector, parseIntVector},
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"import", k_type_import, parseImport},
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"include", k_type_include, parseInclude},
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(uca_rules)", k_type_plugin_uca_rules, parseUCARules},
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(collation)", k_type_plugin_collation, NULL /* not implemented yet */},
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(transliterator)", k_type_plugin_transliterator, parseTransliterator},
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(dependency)", k_type_plugin_dependency, parseDependency},
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"reserved", NULL, NULL}
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
176959d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid initParser()
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_string,    "string",    6);
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_binary,    "binary",    6);
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_bin,       "bin",       3);
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_table,     "table",     5);
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_table_no_fallback,     "table(nofallback)",         17);
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_int,       "int",       3);
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_integer,   "integer",   7);
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_array,     "array",     5);
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_alias,     "alias",     5);
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_intvector, "intvector", 9);
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_import,    "import",    6);
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_include,   "include",   7);
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_uca_rules,      "process(uca_rules)",        18);
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_collation,      "process(collation)",        18);
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_transliterator, "process(transliterator)",   23);
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_dependency,     "process(dependency)",       19);
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1790103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline UBool isTable(enum EResourceType type) {
1791fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return (UBool)(type==RESTYPE_TABLE || type==RESTYPE_TABLE_NO_FALLBACK);
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic enum EResourceType
179527f654740f2a26ad62a5c155af9199af9e69b889clairehoparseResourceType(ParseState* state, UErrorCode *status)
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString        *tokenValue;
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString        comment;
1799fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    enum   EResourceType  result = RESTYPE_UNKNOWN;
1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t              line=0;
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&comment);
180227f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, &comment, &line, status);
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1806fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return RESTYPE_UNKNOWN;
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_ZERO_ERROR;
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Search for normal types */
1812fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    result=RESTYPE_UNKNOWN;
1813fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while ((result=(EResourceType)(result+1)) < RESTYPE_RESERVED) {
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (u_strcmp(tokenValue->fChars, gResourceTypes[result].nameUChars) == 0) {
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Now search for the aliases */
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (u_strcmp(tokenValue->fChars, k_type_int) == 0) {
1820fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result = RESTYPE_INTEGER;
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (u_strcmp(tokenValue->fChars, k_type_bin) == 0) {
1823fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result = RESTYPE_BINARY;
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1825fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    else if (result == RESTYPE_RESERVED) {
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char tokenBuffer[1024];
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u_austrncpy(tokenBuffer, tokenValue->fChars, sizeof(tokenBuffer));
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tokenBuffer[sizeof(tokenBuffer) - 1] = 0;
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "unknown resource type '%s'", tokenBuffer);
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* parse a non-top-level resource */
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
183827f654740f2a26ad62a5c155af9199af9e69b889clairehoparseResource(ParseState* state, char *tag, const struct UString *comment, UErrorCode *status)
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType      token;
1841fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    enum   EResourceType  resType = RESTYPE_UNKNOWN;
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ParseResourceFunction *parseFunction = NULL;
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString        *tokenValue;
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t                 startline;
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t                 line;
1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1847103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
184827f654740f2a26ad62a5c155af9199af9e69b889claireho    token = getToken(state, &tokenValue, NULL, &startline, status);
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" resource %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* name . [ ':' type ] '{' resource '}' */
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* This function parses from the colon onwards.  If the colon is present, parse the
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    type then try to parse a resource of that type.  If there is no explicit type,
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    work it out using the lookahead tokens. */
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (token)
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_EOF:
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "Unexpected EOF encountered");
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_ERROR:
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_COLON:
187027f654740f2a26ad62a5c155af9199af9e69b889claireho        resType = parseResourceType(state, status);
187127f654740f2a26ad62a5c155af9199af9e69b889claireho        expect(state, TOK_OPEN_BRACE, &tokenValue, NULL, &startline, status);
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_OPEN_BRACE:
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "syntax error while reading a resource, expected '{' or ':'");
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1889103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1890fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (resType == RESTYPE_UNKNOWN)
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* No explicit type, so try to work it out.  At this point, we've read the first '{'.
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        We could have any of the following:
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { {         => array (nested)
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { :/}       => array
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string ,  => string array
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string {  => table
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string :/{    => table
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string }      => string
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
190427f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, NULL, &line, NULL,status);
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_OPEN_BRACE || token == TOK_COLON ||token ==TOK_CLOSE_BRACE )
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1913fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            resType = RESTYPE_ARRAY;
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (token == TOK_STRING)
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
191727f654740f2a26ad62a5c155af9199af9e69b889claireho            token = peekToken(state, 1, NULL, &line, NULL, status);
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(*status))
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch (token)
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1926fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_COMMA:         resType = RESTYPE_ARRAY;  break;
1927fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_OPEN_BRACE:    resType = RESTYPE_TABLE;  break;
1928fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_CLOSE_BRACE:   resType = RESTYPE_STRING; break;
1929fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_COLON:         resType = RESTYPE_TABLE;  break;
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            default:
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INVALID_FORMAT_ERROR;
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(line, "Unexpected token after string, expected ',', '{' or '}'");
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "Unexpected token after '{'");
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* printf("Type guessed as %s\n", resourceNames[resType]); */
1944fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else if(resType == RESTYPE_TABLE_NO_FALLBACK) {
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "error: %s resource type not valid except on top bundle level", gResourceTypes[resType].nameChars);
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1950103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We should now know what we need to parse next, so call the appropriate parser
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    function and return. */
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    parseFunction = gResourceTypes[resType].parseFunction;
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (parseFunction != NULL) {
195527f654740f2a26ad62a5c155af9199af9e69b889claireho        return parseFunction(state, tag, startline, comment, status);
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INTERNAL_PROGRAM_ERROR;
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "internal error: %s resource type found and not handled", gResourceTypes[resType].nameChars);
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* parse the top-level resource */
1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct SRBRoot *
1967fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusparse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *filename,
196859d709d503bab6e2b61931737e662dd293b40578ccornelius      UBool makeBinaryCollation, UBool omitCollationRules, UErrorCode *status)
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    comment;
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           line;
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum EResourceType bundleType;
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum ETokenType    token;
197527f654740f2a26ad62a5c155af9199af9e69b889claireho    ParseState state;
197627f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t i;
1977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1978103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
197927f654740f2a26ad62a5c155af9199af9e69b889claireho    for (i = 0; i < MAX_LOOKAHEAD + 1; i++)
198027f654740f2a26ad62a5c155af9199af9e69b889claireho    {
198127f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_init(&state.lookahead[i].value);
198227f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_init(&state.lookahead[i].comment);
198327f654740f2a26ad62a5c155af9199af9e69b889claireho    }
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198527f654740f2a26ad62a5c155af9199af9e69b889claireho    initLookahead(&state, buf, status);
1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198727f654740f2a26ad62a5c155af9199af9e69b889claireho    state.inputdir       = inputDir;
198827f654740f2a26ad62a5c155af9199af9e69b889claireho    state.inputdirLength = (state.inputdir != NULL) ? (uint32_t)uprv_strlen(state.inputdir) : 0;
198927f654740f2a26ad62a5c155af9199af9e69b889claireho    state.outputdir       = outputDir;
199027f654740f2a26ad62a5c155af9199af9e69b889claireho    state.outputdirLength = (state.outputdir != NULL) ? (uint32_t)uprv_strlen(state.outputdir) : 0;
1991fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    state.filename = filename;
1992103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    state.makeBinaryCollation = makeBinaryCollation;
199359d709d503bab6e2b61931737e662dd293b40578ccornelius    state.omitCollationRules = omitCollationRules;
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&comment);
199627f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(&state, TOK_STRING, &tokenValue, &comment, NULL, status);
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1998c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    state.bundle = new SRBRoot(&comment, FALSE, *status);
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
200027f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state.bundle == NULL || U_FAILURE(*status))
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2006c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    state.bundle->setLocale(tokenValue->fChars, *status);
200727f654740f2a26ad62a5c155af9199af9e69b889claireho
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* The following code is to make Empty bundle work no matter with :table specifer or not */
200927f654740f2a26ad62a5c155af9199af9e69b889claireho    token = getToken(&state, NULL, NULL, &line, status);
2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(token==TOK_COLON) {
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status=U_ZERO_ERROR;
201227f654740f2a26ad62a5c155af9199af9e69b889claireho        bundleType=parseResourceType(&state, status);
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isTable(bundleType))
2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
201627f654740f2a26ad62a5c155af9199af9e69b889claireho            expect(&state, TOK_OPEN_BRACE, NULL, NULL, &line, status);
2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_PARSE_ERROR;
2021103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* not a colon */
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(token==TOK_OPEN_BRACE)
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_ZERO_ERROR;
2030fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            bundleType=RESTYPE_TABLE;
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* neither colon nor open brace */
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_PARSE_ERROR;
2036fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            bundleType=RESTYPE_UNKNOWN;
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "parse error, did not find open-brace '{' or colon ':', stopped with %s", u_errorName(*status));
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2043c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete state.bundle;
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2047fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(bundleType==RESTYPE_TABLE_NO_FALLBACK) {
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Parse a top-level table with the table(nofallback) declaration.
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * This is the same as a regular table, but also sets the
2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] .
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
2053c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        state.bundle->fNoFallback=TRUE;
2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* top-level tables need not handle special table names like "collations" */
2056c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    assert(!state.bundle->fIsPoolBundle);
2057c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    assert(state.bundle->fRoot->fType == URES_TABLE);
2058c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource *rootTable = static_cast<TableResource *>(state.bundle->fRoot);
2059c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    realParseTable(&state, rootTable, NULL, line, status);
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(dependencyArray!=NULL){
2061c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        rootTable->add(dependencyArray, 0, *status);
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dependencyArray = NULL;
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2064103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius   if (U_FAILURE(*status))
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2066c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete state.bundle;
2067c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        res_close(dependencyArray);
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207127f654740f2a26ad62a5c155af9199af9e69b889claireho    if (getToken(&state, NULL, NULL, &line, status) != TOK_EOF)
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        warning(line, "extraneous text after resource bundle (perhaps unmatched braces)");
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isStrict()){
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
208027f654740f2a26ad62a5c155af9199af9e69b889claireho    cleanupLookahead(&state);
2081c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ustr_deinit(&comment);
208227f654740f2a26ad62a5c155af9199af9e69b889claireho    return state.bundle;
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2084