~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to Externals/LibXML/parser.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
 
3
 *            implemented on top of the SAX interfaces
 
4
 *
 
5
 * References:
 
6
 *   The XML specification:
 
7
 *     http://www.w3.org/TR/REC-xml
 
8
 *   Original 1.0 version:
 
9
 *     http://www.w3.org/TR/1998/REC-xml-19980210
 
10
 *   XML second edition working draft
 
11
 *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
 
12
 *
 
13
 * Okay this is a big file, the parser core is around 7000 lines, then it
 
14
 * is followed by the progressive parser top routines, then the various
 
15
 * high level APIs to call the parser and a few miscellaneous functions.
 
16
 * A number of helper functions and deprecated ones have been moved to
 
17
 * parserInternals.c to reduce this file size.
 
18
 * As much as possible the functions are associated with their relative
 
19
 * production in the XML specification. A few productions defining the
 
20
 * different ranges of character are actually implanted either in 
 
21
 * parserInternals.h or parserInternals.c
 
22
 * The DOM tree build is realized from the default SAX callbacks in
 
23
 * the module SAX.c.
 
24
 * The routines doing the validation checks are in valid.c and called either
 
25
 * from the SAX callbacks or as standalone functions using a preparsed
 
26
 * document.
 
27
 *
 
28
 * See Copyright for the status of this software.
 
29
 *
 
30
 * daniel@veillard.com
 
31
 */
 
32
 
 
33
#define IN_LIBXML
 
34
#include "libxml.h"
 
35
 
 
36
#if defined(WIN32) && !defined (__CYGWIN__)
 
37
#define XML_DIR_SEP '\\'
 
38
#else
 
39
#define XML_DIR_SEP '/'
 
40
#endif
 
41
 
 
42
#include <stdlib.h>
 
43
#include <string.h>
 
44
#include <stdarg.h>
 
45
#include <libxml/xmlmemory.h>
 
46
#include <libxml/threads.h>
 
47
#include <libxml/globals.h>
 
48
#include <libxml/tree.h>
 
49
#include <libxml/parser.h>
 
50
#include <libxml/parserInternals.h>
 
51
#include <libxml/valid.h>
 
52
#include <libxml/entities.h>
 
53
#include <libxml/xmlerror.h>
 
54
#include <libxml/encoding.h>
 
55
#include <libxml/xmlIO.h>
 
56
#include <libxml/uri.h>
 
57
#ifdef LIBXML_CATALOG_ENABLED
 
58
#include <libxml/catalog.h>
 
59
#endif
 
60
#ifdef LIBXML_SCHEMAS_ENABLED
 
61
#include <libxml/xmlschemastypes.h>
 
62
#include <libxml/relaxng.h>
 
63
#endif
 
64
#ifdef HAVE_CTYPE_H
 
65
#include <ctype.h>
 
66
#endif
 
67
#ifdef HAVE_STDLIB_H
 
68
#include <stdlib.h>
 
69
#endif
 
70
#ifdef HAVE_SYS_STAT_H
 
71
#include <sys/stat.h>
 
72
#endif
 
73
#ifdef HAVE_FCNTL_H
 
74
#include <fcntl.h>
 
75
#endif
 
76
#ifdef HAVE_UNISTD_H
 
77
#include <unistd.h>
 
78
#endif
 
79
#ifdef HAVE_ZLIB_H
 
80
#include <zlib.h>
 
81
#endif
 
82
 
 
83
/**
 
84
 * xmlParserMaxDepth:
 
85
 *
 
86
 * arbitrary depth limit for the XML documents that we allow to 
 
87
 * process. This is not a limitation of the parser but a safety 
 
88
 * boundary feature.
 
89
 */
 
90
unsigned int xmlParserMaxDepth = 1024;
 
91
 
 
92
#define SAX2 1
 
93
 
 
94
#define XML_PARSER_BIG_BUFFER_SIZE 300
 
95
#define XML_PARSER_BUFFER_SIZE 100
 
96
 
 
97
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
 
98
 
 
99
/*
 
100
 * List of XML prefixed PI allowed by W3C specs
 
101
 */
 
102
 
 
103
static const char *xmlW3CPIs[] = {
 
104
    "xml-stylesheet",
 
105
    NULL
 
106
};
 
107
 
 
108
 
 
109
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
 
110
xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
 
111
                                       const xmlChar **str);
 
112
 
 
113
static xmlParserErrors
 
114
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
 
115
                      xmlSAXHandlerPtr sax,
 
116
                      void *user_data, int depth, const xmlChar *URL,
 
117
                      const xmlChar *ID, xmlNodePtr *list);
 
118
 
 
119
#ifdef LIBXML_LEGACY_ENABLED
 
120
static void
 
121
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
 
122
                      xmlNodePtr lastNode);
 
123
#endif /* LIBXML_LEGACY_ENABLED */
 
124
 
 
125
static xmlParserErrors
 
126
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 
127
                      const xmlChar *string, void *user_data, xmlNodePtr *lst);
 
128
 
 
129
static int
 
130
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
 
131
 
 
132
/************************************************************************
 
133
 *                                                                      *
 
134
 *              Some factorized error routines                          *
 
135
 *                                                                      *
 
136
 ************************************************************************/
 
137
 
 
138
/**
 
139
 * xmlErrAttributeDup:
 
140
 * @ctxt:  an XML parser context
 
141
 * @prefix:  the attribute prefix
 
142
 * @localname:  the attribute localname
 
143
 *
 
144
 * Handle a redefinition of attribute error
 
145
 */
 
146
static void
 
147
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
 
148
                   const xmlChar * localname)
 
149
{
 
150
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
151
        (ctxt->instate == XML_PARSER_EOF))
 
152
        return;
 
153
    if (ctxt != NULL)
 
154
        ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
 
155
    if (prefix == NULL)
 
156
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
 
157
                        ctxt->errNo, XML_ERR_FATAL, NULL, 0,
 
158
                        (const char *) localname, NULL, NULL, 0, 0,
 
159
                        "Attribute %s redefined\n", localname);
 
160
    else
 
161
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
 
162
                        ctxt->errNo, XML_ERR_FATAL, NULL, 0,
 
163
                        (const char *) prefix, (const char *) localname,
 
164
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
 
165
                        localname);
 
166
    if (ctxt != NULL) {
 
167
        ctxt->wellFormed = 0;
 
168
        if (ctxt->recovery == 0)
 
169
            ctxt->disableSAX = 1;
 
170
    }
 
171
}
 
172
 
 
173
/**
 
174
 * xmlFatalErr:
 
175
 * @ctxt:  an XML parser context
 
176
 * @error:  the error number
 
177
 * @extra:  extra information string
 
178
 *
 
179
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
180
 */
 
181
static void
 
182
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
 
183
{
 
184
    const char *errmsg;
 
185
 
 
186
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
187
        (ctxt->instate == XML_PARSER_EOF))
 
188
        return;
 
189
    switch (error) {
 
190
        case XML_ERR_INVALID_HEX_CHARREF:
 
191
            errmsg = "CharRef: invalid hexadecimal value\n";
 
192
            break;
 
193
        case XML_ERR_INVALID_DEC_CHARREF:
 
194
            errmsg = "CharRef: invalid decimal value\n";
 
195
            break;
 
196
        case XML_ERR_INVALID_CHARREF:
 
197
            errmsg = "CharRef: invalid value\n";
 
198
            break;
 
199
        case XML_ERR_INTERNAL_ERROR:
 
200
            errmsg = "internal error";
 
201
            break;
 
202
        case XML_ERR_PEREF_AT_EOF:
 
203
            errmsg = "PEReference at end of document\n";
 
204
            break;
 
205
        case XML_ERR_PEREF_IN_PROLOG:
 
206
            errmsg = "PEReference in prolog\n";
 
207
            break;
 
208
        case XML_ERR_PEREF_IN_EPILOG:
 
209
            errmsg = "PEReference in epilog\n";
 
210
            break;
 
211
        case XML_ERR_PEREF_NO_NAME:
 
212
            errmsg = "PEReference: no name\n";
 
213
            break;
 
214
        case XML_ERR_PEREF_SEMICOL_MISSING:
 
215
            errmsg = "PEReference: expecting ';'\n";
 
216
            break;
 
217
        case XML_ERR_ENTITY_LOOP:
 
218
            errmsg = "Detected an entity reference loop\n";
 
219
            break;
 
220
        case XML_ERR_ENTITY_NOT_STARTED:
 
221
            errmsg = "EntityValue: \" or ' expected\n";
 
222
            break;
 
223
        case XML_ERR_ENTITY_PE_INTERNAL:
 
224
            errmsg = "PEReferences forbidden in internal subset\n";
 
225
            break;
 
226
        case XML_ERR_ENTITY_NOT_FINISHED:
 
227
            errmsg = "EntityValue: \" or ' expected\n";
 
228
            break;
 
229
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
 
230
            errmsg = "AttValue: \" or ' expected\n";
 
231
            break;
 
232
        case XML_ERR_LT_IN_ATTRIBUTE:
 
233
            errmsg = "Unescaped '<' not allowed in attributes values\n";
 
234
            break;
 
235
        case XML_ERR_LITERAL_NOT_STARTED:
 
236
            errmsg = "SystemLiteral \" or ' expected\n";
 
237
            break;
 
238
        case XML_ERR_LITERAL_NOT_FINISHED:
 
239
            errmsg = "Unfinished System or Public ID \" or ' expected\n";
 
240
            break;
 
241
        case XML_ERR_MISPLACED_CDATA_END:
 
242
            errmsg = "Sequence ']]>' not allowed in content\n";
 
243
            break;
 
244
        case XML_ERR_URI_REQUIRED:
 
245
            errmsg = "SYSTEM or PUBLIC, the URI is missing\n";
 
246
            break;
 
247
        case XML_ERR_PUBID_REQUIRED:
 
248
            errmsg = "PUBLIC, the Public Identifier is missing\n";
 
249
            break;
 
250
        case XML_ERR_HYPHEN_IN_COMMENT:
 
251
            errmsg = "Comment must not contain '--' (double-hyphen)\n";
 
252
            break;
 
253
        case XML_ERR_PI_NOT_STARTED:
 
254
            errmsg = "xmlParsePI : no target name\n";
 
255
            break;
 
256
        case XML_ERR_RESERVED_XML_NAME:
 
257
            errmsg = "Invalid PI name\n";
 
258
            break;
 
259
        case XML_ERR_NOTATION_NOT_STARTED:
 
260
            errmsg = "NOTATION: Name expected here\n";
 
261
            break;
 
262
        case XML_ERR_NOTATION_NOT_FINISHED:
 
263
            errmsg = "'>' required to close NOTATION declaration\n";
 
264
            break;
 
265
        case XML_ERR_VALUE_REQUIRED:
 
266
            errmsg = "Entity value required\n";
 
267
            break;
 
268
        case XML_ERR_URI_FRAGMENT:
 
269
            errmsg = "Fragment not allowed";
 
270
            break;
 
271
        case XML_ERR_ATTLIST_NOT_STARTED:
 
272
            errmsg = "'(' required to start ATTLIST enumeration\n";
 
273
            break;
 
274
        case XML_ERR_NMTOKEN_REQUIRED:
 
275
            errmsg = "NmToken expected in ATTLIST enumeration\n";
 
276
            break;
 
277
        case XML_ERR_ATTLIST_NOT_FINISHED:
 
278
            errmsg = "')' required to finish ATTLIST enumeration\n";
 
279
            break;
 
280
        case XML_ERR_MIXED_NOT_STARTED:
 
281
            errmsg = "MixedContentDecl : '|' or ')*' expected\n";
 
282
            break;
 
283
        case XML_ERR_PCDATA_REQUIRED:
 
284
            errmsg = "MixedContentDecl : '#PCDATA' expected\n";
 
285
            break;
 
286
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
 
287
            errmsg = "ContentDecl : Name or '(' expected\n";
 
288
            break;
 
289
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
 
290
            errmsg = "ContentDecl : ',' '|' or ')' expected\n";
 
291
            break;
 
292
        case XML_ERR_PEREF_IN_INT_SUBSET:
 
293
            errmsg =
 
294
                "PEReference: forbidden within markup decl in internal subset\n";
 
295
            break;
 
296
        case XML_ERR_GT_REQUIRED:
 
297
            errmsg = "expected '>'\n";
 
298
            break;
 
299
        case XML_ERR_CONDSEC_INVALID:
 
300
            errmsg = "XML conditional section '[' expected\n";
 
301
            break;
 
302
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
 
303
            errmsg = "Content error in the external subset\n";
 
304
            break;
 
305
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
 
306
            errmsg =
 
307
                "conditional section INCLUDE or IGNORE keyword expected\n";
 
308
            break;
 
309
        case XML_ERR_CONDSEC_NOT_FINISHED:
 
310
            errmsg = "XML conditional section not closed\n";
 
311
            break;
 
312
        case XML_ERR_XMLDECL_NOT_STARTED:
 
313
            errmsg = "Text declaration '<?xml' required\n";
 
314
            break;
 
315
        case XML_ERR_XMLDECL_NOT_FINISHED:
 
316
            errmsg = "parsing XML declaration: '?>' expected\n";
 
317
            break;
 
318
        case XML_ERR_EXT_ENTITY_STANDALONE:
 
319
            errmsg = "external parsed entities cannot be standalone\n";
 
320
            break;
 
321
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
 
322
            errmsg = "EntityRef: expecting ';'\n";
 
323
            break;
 
324
        case XML_ERR_DOCTYPE_NOT_FINISHED:
 
325
            errmsg = "DOCTYPE improperly terminated\n";
 
326
            break;
 
327
        case XML_ERR_LTSLASH_REQUIRED:
 
328
            errmsg = "EndTag: '</' not found\n";
 
329
            break;
 
330
        case XML_ERR_EQUAL_REQUIRED:
 
331
            errmsg = "expected '='\n";
 
332
            break;
 
333
        case XML_ERR_STRING_NOT_CLOSED:
 
334
            errmsg = "String not closed expecting \" or '\n";
 
335
            break;
 
336
        case XML_ERR_STRING_NOT_STARTED:
 
337
            errmsg = "String not started expecting ' or \"\n";
 
338
            break;
 
339
        case XML_ERR_ENCODING_NAME:
 
340
            errmsg = "Invalid XML encoding name\n";
 
341
            break;
 
342
        case XML_ERR_STANDALONE_VALUE:
 
343
            errmsg = "standalone accepts only 'yes' or 'no'\n";
 
344
            break;
 
345
        case XML_ERR_DOCUMENT_EMPTY:
 
346
            errmsg = "Document is empty\n";
 
347
            break;
 
348
        case XML_ERR_DOCUMENT_END:
 
349
            errmsg = "Extra content at the end of the document\n";
 
350
            break;
 
351
        case XML_ERR_NOT_WELL_BALANCED:
 
352
            errmsg = "chunk is not well balanced\n";
 
353
            break;
 
354
        case XML_ERR_EXTRA_CONTENT:
 
355
            errmsg = "extra content at the end of well balanced chunk\n";
 
356
            break;
 
357
        case XML_ERR_VERSION_MISSING:
 
358
            errmsg = "Malformed declaration expecting version\n";
 
359
            break;
 
360
#if 0
 
361
        case:
 
362
            errmsg = "\n";
 
363
            break;
 
364
#endif
 
365
        default:
 
366
            errmsg = "Unregistered error message\n";
 
367
    }
 
368
    if (ctxt != NULL)
 
369
        ctxt->errNo = error;
 
370
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
 
371
                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, errmsg,
 
372
                    info);
 
373
    if (ctxt != NULL) {
 
374
        ctxt->wellFormed = 0;
 
375
        if (ctxt->recovery == 0)
 
376
            ctxt->disableSAX = 1;
 
377
    }
 
378
}
 
379
 
 
380
/**
 
381
 * xmlFatalErrMsg:
 
382
 * @ctxt:  an XML parser context
 
383
 * @error:  the error number
 
384
 * @msg:  the error message
 
385
 *
 
386
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
387
 */
 
388
static void
 
389
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
390
               const char *msg)
 
391
{
 
392
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
393
        (ctxt->instate == XML_PARSER_EOF))
 
394
        return;
 
395
    if (ctxt != NULL)
 
396
        ctxt->errNo = error;
 
397
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
 
398
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg);
 
399
    if (ctxt != NULL) {
 
400
        ctxt->wellFormed = 0;
 
401
        if (ctxt->recovery == 0)
 
402
            ctxt->disableSAX = 1;
 
403
    }
 
404
}
 
405
 
 
406
/**
 
407
 * xmlWarningMsg:
 
408
 * @ctxt:  an XML parser context
 
409
 * @error:  the error number
 
410
 * @msg:  the error message
 
411
 * @str1:  extra data
 
412
 * @str2:  extra data
 
413
 *
 
414
 * Handle a warning.
 
415
 */
 
416
static void
 
417
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
418
              const char *msg, const xmlChar *str1, const xmlChar *str2)
 
419
{
 
420
    xmlStructuredErrorFunc schannel = NULL;
 
421
    
 
422
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
423
        (ctxt->instate == XML_PARSER_EOF))
 
424
        return;
 
425
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
 
426
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
 
427
        schannel = ctxt->sax->serror;
 
428
    __xmlRaiseError(schannel,
 
429
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
 
430
                    ctxt->userData,
 
431
                    ctxt, NULL, XML_FROM_PARSER, error,
 
432
                    XML_ERR_WARNING, NULL, 0,
 
433
                    (const char *) str1, (const char *) str2, NULL, 0, 0,
 
434
                    msg, (const char *) str1, (const char *) str2);
 
435
}
 
436
 
 
437
/**
 
438
 * xmlValidityError:
 
439
 * @ctxt:  an XML parser context
 
440
 * @error:  the error number
 
441
 * @msg:  the error message
 
442
 * @str1:  extra data
 
443
 *
 
444
 * Handle a validity error.
 
445
 */
 
446
static void
 
447
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
448
              const char *msg, const xmlChar *str1)
 
449
{
 
450
    xmlStructuredErrorFunc schannel = NULL;
 
451
 
 
452
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
453
        (ctxt->instate == XML_PARSER_EOF))
 
454
        return;
 
455
    if (ctxt != NULL) {
 
456
        ctxt->errNo = error;
 
457
        if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
 
458
            schannel = ctxt->sax->serror;
 
459
    }
 
460
    __xmlRaiseError(schannel,
 
461
                    ctxt->vctxt.error, ctxt->vctxt.userData,
 
462
                    ctxt, NULL, XML_FROM_DTD, error,
 
463
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
 
464
                    NULL, NULL, 0, 0,
 
465
                    msg, (const char *) str1);
 
466
    if (ctxt != NULL) {
 
467
        ctxt->valid = 0;
 
468
    }
 
469
}
 
470
 
 
471
/**
 
472
 * xmlFatalErrMsgInt:
 
473
 * @ctxt:  an XML parser context
 
474
 * @error:  the error number
 
475
 * @msg:  the error message
 
476
 * @val:  an integer value
 
477
 *
 
478
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
479
 */
 
480
static void
 
481
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
482
                  const char *msg, int val)
 
483
{
 
484
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
485
        (ctxt->instate == XML_PARSER_EOF))
 
486
        return;
 
487
    if (ctxt != NULL)
 
488
        ctxt->errNo = error;
 
489
    __xmlRaiseError(NULL, NULL, NULL,
 
490
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
 
491
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
 
492
    if (ctxt != NULL) {
 
493
        ctxt->wellFormed = 0;
 
494
        if (ctxt->recovery == 0)
 
495
            ctxt->disableSAX = 1;
 
496
    }
 
497
}
 
498
 
 
499
/**
 
500
 * xmlFatalErrMsgStrIntStr:
 
501
 * @ctxt:  an XML parser context
 
502
 * @error:  the error number
 
503
 * @msg:  the error message
 
504
 * @str1:  an string info
 
505
 * @val:  an integer value
 
506
 * @str2:  an string info
 
507
 *
 
508
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
509
 */
 
510
static void
 
511
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
512
                  const char *msg, const xmlChar *str1, int val, 
 
513
                  const xmlChar *str2)
 
514
{
 
515
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
516
        (ctxt->instate == XML_PARSER_EOF))
 
517
        return;
 
518
    if (ctxt != NULL)
 
519
        ctxt->errNo = error;
 
520
    __xmlRaiseError(NULL, NULL, NULL,
 
521
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
 
522
                    NULL, 0, (const char *) str1, (const char *) str2,
 
523
                    NULL, val, 0, msg, str1, val, str2);
 
524
    if (ctxt != NULL) {
 
525
        ctxt->wellFormed = 0;
 
526
        if (ctxt->recovery == 0)
 
527
            ctxt->disableSAX = 1;
 
528
    }
 
529
}
 
530
 
 
531
/**
 
532
 * xmlFatalErrMsgStr:
 
533
 * @ctxt:  an XML parser context
 
534
 * @error:  the error number
 
535
 * @msg:  the error message
 
536
 * @val:  a string value
 
537
 *
 
538
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
539
 */
 
540
static void
 
541
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
542
                  const char *msg, const xmlChar * val)
 
543
{
 
544
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
545
        (ctxt->instate == XML_PARSER_EOF))
 
546
        return;
 
547
    if (ctxt != NULL)
 
548
        ctxt->errNo = error;
 
549
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
 
550
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
 
551
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
 
552
                    val);
 
553
    if (ctxt != NULL) {
 
554
        ctxt->wellFormed = 0;
 
555
        if (ctxt->recovery == 0)
 
556
            ctxt->disableSAX = 1;
 
557
    }
 
558
}
 
559
 
 
560
/**
 
561
 * xmlErrMsgStr:
 
562
 * @ctxt:  an XML parser context
 
563
 * @error:  the error number
 
564
 * @msg:  the error message
 
565
 * @val:  a string value
 
566
 *
 
567
 * Handle a non fatal parser error
 
568
 */
 
569
static void
 
570
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
571
                  const char *msg, const xmlChar * val)
 
572
{
 
573
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
574
        (ctxt->instate == XML_PARSER_EOF))
 
575
        return;
 
576
    if (ctxt != NULL)
 
577
        ctxt->errNo = error;
 
578
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
 
579
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
 
580
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
 
581
                    val);
 
582
}
 
583
 
 
584
/**
 
585
 * xmlNsErr:
 
586
 * @ctxt:  an XML parser context
 
587
 * @error:  the error number
 
588
 * @msg:  the message
 
589
 * @info1:  extra information string
 
590
 * @info2:  extra information string
 
591
 *
 
592
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
593
 */
 
594
static void
 
595
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
596
         const char *msg,
 
597
         const xmlChar * info1, const xmlChar * info2,
 
598
         const xmlChar * info3)
 
599
{
 
600
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
601
        (ctxt->instate == XML_PARSER_EOF))
 
602
        return;
 
603
    if (ctxt != NULL)
 
604
        ctxt->errNo = error;
 
605
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
 
606
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
 
607
                    (const char *) info2, (const char *) info3, 0, 0, msg,
 
608
                    info1, info2, info3);
 
609
    if (ctxt != NULL)
 
610
        ctxt->nsWellFormed = 0;
 
611
}
 
612
 
 
613
/************************************************************************
 
614
 *                                                                      *
 
615
 *              Library wide options                                    *
 
616
 *                                                                      *
 
617
 ************************************************************************/
 
618
 
 
619
/**
 
620
  * xmlHasFeature:
 
621
  * @feature: the feature to be examined
 
622
  *
 
623
  * Examines if the library has been compiled with a given feature.
 
624
  *
 
625
  * Returns a non-zero value if the feature exist, otherwise zero.
 
626
  * Returns zero (0) if the feature does not exist or an unknown
 
627
  * unknown feature is requested, non-zero otherwise.
 
628
  */
 
629
int
 
630
xmlHasFeature(xmlFeature feature)
 
631
{
 
632
    switch (feature) {
 
633
        case XML_WITH_THREAD:
 
634
#ifdef LIBXML_THREAD_ENABLED
 
635
            return(1);
 
636
#else
 
637
            return(0);
 
638
#endif
 
639
        case XML_WITH_TREE:
 
640
#ifdef LIBXML_TREE_ENABLED
 
641
            return(1);
 
642
#else
 
643
            return(0);
 
644
#endif
 
645
        case XML_WITH_OUTPUT:
 
646
#ifdef LIBXML_OUTPUT_ENABLED
 
647
            return(1);
 
648
#else
 
649
            return(0);
 
650
#endif
 
651
        case XML_WITH_PUSH:
 
652
#ifdef LIBXML_PUSH_ENABLED
 
653
            return(1);
 
654
#else
 
655
            return(0);
 
656
#endif
 
657
        case XML_WITH_READER:
 
658
#ifdef LIBXML_READER_ENABLED
 
659
            return(1);
 
660
#else
 
661
            return(0);
 
662
#endif
 
663
        case XML_WITH_PATTERN:
 
664
#ifdef LIBXML_PATTERN_ENABLED
 
665
            return(1);
 
666
#else
 
667
            return(0);
 
668
#endif
 
669
        case XML_WITH_WRITER:
 
670
#ifdef LIBXML_WRITER_ENABLED
 
671
            return(1);
 
672
#else
 
673
            return(0);
 
674
#endif
 
675
        case XML_WITH_SAX1:
 
676
#ifdef LIBXML_SAX1_ENABLED
 
677
            return(1);
 
678
#else
 
679
            return(0);
 
680
#endif
 
681
        case XML_WITH_FTP:
 
682
#ifdef LIBXML_FTP_ENABLED
 
683
            return(1);
 
684
#else
 
685
            return(0);
 
686
#endif
 
687
        case XML_WITH_HTTP:
 
688
#ifdef LIBXML_HTTP_ENABLED
 
689
            return(1);
 
690
#else
 
691
            return(0);
 
692
#endif
 
693
        case XML_WITH_VALID:
 
694
#ifdef LIBXML_VALID_ENABLED
 
695
            return(1);
 
696
#else
 
697
            return(0);
 
698
#endif
 
699
        case XML_WITH_HTML:
 
700
#ifdef LIBXML_HTML_ENABLED
 
701
            return(1);
 
702
#else
 
703
            return(0);
 
704
#endif
 
705
        case XML_WITH_LEGACY:
 
706
#ifdef LIBXML_LEGACY_ENABLED
 
707
            return(1);
 
708
#else
 
709
            return(0);
 
710
#endif
 
711
        case XML_WITH_C14N:
 
712
#ifdef LIBXML_C14N_ENABLED
 
713
            return(1);
 
714
#else
 
715
            return(0);
 
716
#endif
 
717
        case XML_WITH_CATALOG:
 
718
#ifdef LIBXML_CATALOG_ENABLED
 
719
            return(1);
 
720
#else
 
721
            return(0);
 
722
#endif
 
723
        case XML_WITH_XPATH:
 
724
#ifdef LIBXML_XPATH_ENABLED
 
725
            return(1);
 
726
#else
 
727
            return(0);
 
728
#endif
 
729
        case XML_WITH_XPTR:
 
730
#ifdef LIBXML_XPTR_ENABLED
 
731
            return(1);
 
732
#else
 
733
            return(0);
 
734
#endif
 
735
        case XML_WITH_XINCLUDE:
 
736
#ifdef LIBXML_XINCLUDE_ENABLED
 
737
            return(1);
 
738
#else
 
739
            return(0);
 
740
#endif
 
741
        case XML_WITH_ICONV:
 
742
#ifdef LIBXML_ICONV_ENABLED
 
743
            return(1);
 
744
#else
 
745
            return(0);
 
746
#endif
 
747
        case XML_WITH_ISO8859X:
 
748
#ifdef LIBXML_ISO8859X_ENABLED
 
749
            return(1);
 
750
#else
 
751
            return(0);
 
752
#endif
 
753
        case XML_WITH_UNICODE:
 
754
#ifdef LIBXML_UNICODE_ENABLED
 
755
            return(1);
 
756
#else
 
757
            return(0);
 
758
#endif
 
759
        case XML_WITH_REGEXP:
 
760
#ifdef LIBXML_REGEXP_ENABLED
 
761
            return(1);
 
762
#else
 
763
            return(0);
 
764
#endif
 
765
        case XML_WITH_AUTOMATA:
 
766
#ifdef LIBXML_AUTOMATA_ENABLED
 
767
            return(1);
 
768
#else
 
769
            return(0);
 
770
#endif
 
771
        case XML_WITH_EXPR:
 
772
#ifdef LIBXML_EXPR_ENABLED
 
773
            return(1);
 
774
#else
 
775
            return(0);
 
776
#endif
 
777
        case XML_WITH_SCHEMAS:
 
778
#ifdef LIBXML_SCHEMAS_ENABLED
 
779
            return(1);
 
780
#else
 
781
            return(0);
 
782
#endif
 
783
        case XML_WITH_SCHEMATRON:
 
784
#ifdef LIBXML_SCHEMATRON_ENABLED
 
785
            return(1);
 
786
#else
 
787
            return(0);
 
788
#endif
 
789
        case XML_WITH_MODULES:
 
790
#ifdef LIBXML_MODULES_ENABLED
 
791
            return(1);
 
792
#else
 
793
            return(0);
 
794
#endif
 
795
        case XML_WITH_DEBUG:
 
796
#ifdef LIBXML_DEBUG_ENABLED
 
797
            return(1);
 
798
#else
 
799
            return(0);
 
800
#endif
 
801
        case XML_WITH_DEBUG_MEM:
 
802
#ifdef DEBUG_MEMORY_LOCATION
 
803
            return(1);
 
804
#else
 
805
            return(0);
 
806
#endif
 
807
        case XML_WITH_DEBUG_RUN:
 
808
#ifdef LIBXML_DEBUG_RUNTIME
 
809
            return(1);
 
810
#else
 
811
            return(0);
 
812
#endif 
 
813
        case XML_WITH_ZLIB:
 
814
#ifdef LIBXML_ZLIB_ENABLED
 
815
            return(1);
 
816
#else
 
817
            return(0);
 
818
#endif
 
819
        default:
 
820
            break;
 
821
     }
 
822
     return(0);
 
823
}
 
824
 
 
825
/************************************************************************
 
826
 *                                                                      *
 
827
 *              SAX2 defaulted attributes handling                      *
 
828
 *                                                                      *
 
829
 ************************************************************************/
 
830
 
 
831
/**
 
832
 * xmlDetectSAX2:
 
833
 * @ctxt:  an XML parser context
 
834
 *
 
835
 * Do the SAX2 detection and specific intialization
 
836
 */
 
837
static void
 
838
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
 
839
    if (ctxt == NULL) return;
 
840
#ifdef LIBXML_SAX1_ENABLED
 
841
    if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
 
842
        ((ctxt->sax->startElementNs != NULL) ||
 
843
         (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
 
844
#else
 
845
    ctxt->sax2 = 1;
 
846
#endif /* LIBXML_SAX1_ENABLED */
 
847
 
 
848
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
849
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
850
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
851
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || 
 
852
                (ctxt->str_xml_ns == NULL)) {
 
853
        xmlErrMemory(ctxt, NULL);
 
854
    }
 
855
}
 
856
 
 
857
typedef struct _xmlDefAttrs xmlDefAttrs;
 
858
typedef xmlDefAttrs *xmlDefAttrsPtr;
 
859
struct _xmlDefAttrs {
 
860
    int nbAttrs;        /* number of defaulted attributes on that element */
 
861
    int maxAttrs;       /* the size of the array */
 
862
    const xmlChar *values[4]; /* array of localname/prefix/values */
 
863
};
 
864
 
 
865
/**
 
866
 * xmlAttrNormalizeSpace:
 
867
 * @src: the source string
 
868
 * @dst: the target string
 
869
 *
 
870
 * Normalize the space in non CDATA attribute values:
 
871
 * If the attribute type is not CDATA, then the XML processor MUST further
 
872
 * process the normalized attribute value by discarding any leading and
 
873
 * trailing space (#x20) characters, and by replacing sequences of space
 
874
 * (#x20) characters by a single space (#x20) character.
 
875
 * Note that the size of dst need to be at least src, and if one doesn't need
 
876
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
 
877
 * passing src as dst is just fine.
 
878
 *
 
879
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
 
880
 *         is needed.
 
881
 */
 
882
static xmlChar *
 
883
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
 
884
{
 
885
    if ((src == NULL) || (dst == NULL))
 
886
        return(NULL);
 
887
 
 
888
    while (*src == 0x20) src++;
 
889
    while (*src != 0) {
 
890
        if (*src == 0x20) {
 
891
            while (*src == 0x20) src++;
 
892
            if (*src != 0)
 
893
                *dst++ = 0x20;
 
894
        } else {
 
895
            *dst++ = *src++;
 
896
        }
 
897
    }
 
898
    *dst = 0;
 
899
    if (dst == src)
 
900
       return(NULL);
 
901
    return(dst);
 
902
}
 
903
 
 
904
/**
 
905
 * xmlAttrNormalizeSpace2:
 
906
 * @src: the source string
 
907
 *
 
908
 * Normalize the space in non CDATA attribute values, a slightly more complex
 
909
 * front end to avoid allocation problems when running on attribute values
 
910
 * coming from the input.
 
911
 *
 
912
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
 
913
 *         is needed.
 
914
 */
 
915
static const xmlChar *
 
916
xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, const xmlChar *src, int *len)
 
917
{
 
918
    int i;
 
919
    int remove_head = 0;
 
920
    int need_realloc = 0;
 
921
    const xmlChar *cur;
 
922
 
 
923
    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
 
924
        return(NULL);
 
925
    i = *len;
 
926
    if (i <= 0)
 
927
        return(NULL);
 
928
 
 
929
    cur = src;
 
930
    while (*cur == 0x20) {
 
931
        cur++;
 
932
        remove_head++;
 
933
    }
 
934
    while (*cur != 0) {
 
935
        if (*cur == 0x20) {
 
936
            cur++;
 
937
            if ((*cur == 0x20) || (*cur == 0)) {
 
938
                need_realloc = 1;
 
939
                break;
 
940
            }
 
941
        } else
 
942
            cur++;
 
943
    }
 
944
    if (need_realloc) {
 
945
        xmlChar *ret;
 
946
 
 
947
        ret = xmlStrndup(src + remove_head, i - remove_head + 1);
 
948
        if (ret == NULL) {
 
949
            xmlErrMemory(ctxt, NULL);
 
950
            return(NULL);
 
951
        }
 
952
        xmlAttrNormalizeSpace(ret, ret);
 
953
        *len = (int) strlen((const char *)ret);
 
954
        return(ret);
 
955
    } else if (remove_head) {
 
956
        *len -= remove_head;
 
957
        return(src + remove_head);
 
958
    }
 
959
    return(NULL);
 
960
}
 
961
 
 
962
/**
 
963
 * xmlAddDefAttrs:
 
964
 * @ctxt:  an XML parser context
 
965
 * @fullname:  the element fullname
 
966
 * @fullattr:  the attribute fullname
 
967
 * @value:  the attribute value
 
968
 *
 
969
 * Add a defaulted attribute for an element
 
970
 */
 
971
static void
 
972
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
 
973
               const xmlChar *fullname,
 
974
               const xmlChar *fullattr,
 
975
               const xmlChar *value) {
 
976
    xmlDefAttrsPtr defaults;
 
977
    int len;
 
978
    const xmlChar *name;
 
979
    const xmlChar *prefix;
 
980
 
 
981
    /*
 
982
     * Allows to detect attribute redefinitions
 
983
     */
 
984
    if (ctxt->attsSpecial != NULL) {
 
985
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
 
986
            return;
 
987
    }
 
988
 
 
989
    if (ctxt->attsDefault == NULL) {
 
990
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
 
991
        if (ctxt->attsDefault == NULL)
 
992
            goto mem_error;
 
993
    }
 
994
 
 
995
    /*
 
996
     * split the element name into prefix:localname , the string found
 
997
     * are within the DTD and then not associated to namespace names.
 
998
     */
 
999
    name = xmlSplitQName3(fullname, &len);
 
1000
    if (name == NULL) {
 
1001
        name = xmlDictLookup(ctxt->dict, fullname, -1);
 
1002
        prefix = NULL;
 
1003
    } else {
 
1004
        name = xmlDictLookup(ctxt->dict, name, -1);
 
1005
        prefix = xmlDictLookup(ctxt->dict, fullname, len);
 
1006
    }
 
1007
 
 
1008
    /*
 
1009
     * make sure there is some storage
 
1010
     */
 
1011
    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
 
1012
    if (defaults == NULL) {
 
1013
        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
 
1014
                           (4 * 4) * sizeof(const xmlChar *));
 
1015
        if (defaults == NULL)
 
1016
            goto mem_error;
 
1017
        defaults->nbAttrs = 0;
 
1018
        defaults->maxAttrs = 4;
 
1019
        if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
 
1020
                                defaults, NULL) < 0) {
 
1021
            xmlFree(defaults);
 
1022
            goto mem_error;
 
1023
        }
 
1024
    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
 
1025
        xmlDefAttrsPtr temp;
 
1026
 
 
1027
        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
 
1028
                       (2 * defaults->maxAttrs * 4) * sizeof(const xmlChar *));
 
1029
        if (temp == NULL)
 
1030
            goto mem_error;
 
1031
        defaults = temp;
 
1032
        defaults->maxAttrs *= 2;
 
1033
        if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
 
1034
                                defaults, NULL) < 0) {
 
1035
            xmlFree(defaults);
 
1036
            goto mem_error;
 
1037
        }
 
1038
    }
 
1039
 
 
1040
    /*
 
1041
     * Split the element name into prefix:localname , the string found
 
1042
     * are within the DTD and hen not associated to namespace names.
 
1043
     */
 
1044
    name = xmlSplitQName3(fullattr, &len);
 
1045
    if (name == NULL) {
 
1046
        name = xmlDictLookup(ctxt->dict, fullattr, -1);
 
1047
        prefix = NULL;
 
1048
    } else {
 
1049
        name = xmlDictLookup(ctxt->dict, name, -1);
 
1050
        prefix = xmlDictLookup(ctxt->dict, fullattr, len);
 
1051
    }
 
1052
 
 
1053
    defaults->values[4 * defaults->nbAttrs] = name;
 
1054
    defaults->values[4 * defaults->nbAttrs + 1] = prefix;
 
1055
    /* intern the string and precompute the end */
 
1056
    len = xmlStrlen(value);
 
1057
    value = xmlDictLookup(ctxt->dict, value, len);
 
1058
    defaults->values[4 * defaults->nbAttrs + 2] = value;
 
1059
    defaults->values[4 * defaults->nbAttrs + 3] = value + len;
 
1060
    defaults->nbAttrs++;
 
1061
 
 
1062
    return;
 
1063
 
 
1064
mem_error:
 
1065
    xmlErrMemory(ctxt, NULL);
 
1066
    return;
 
1067
}
 
1068
 
 
1069
/**
 
1070
 * xmlAddSpecialAttr:
 
1071
 * @ctxt:  an XML parser context
 
1072
 * @fullname:  the element fullname
 
1073
 * @fullattr:  the attribute fullname
 
1074
 * @type:  the attribute type
 
1075
 *
 
1076
 * Register this attribute type
 
1077
 */
 
1078
static void
 
1079
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
 
1080
                  const xmlChar *fullname,
 
1081
                  const xmlChar *fullattr,
 
1082
                  int type)
 
1083
{
 
1084
    if (ctxt->attsSpecial == NULL) {
 
1085
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
 
1086
        if (ctxt->attsSpecial == NULL)
 
1087
            goto mem_error;
 
1088
    }
 
1089
 
 
1090
    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
 
1091
        return;
 
1092
 
 
1093
    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
 
1094
                     (void *) (long) type);
 
1095
    return;
 
1096
 
 
1097
mem_error:
 
1098
    xmlErrMemory(ctxt, NULL);
 
1099
    return;
 
1100
}
 
1101
 
 
1102
/**
 
1103
 * xmlCleanSpecialAttrCallback:
 
1104
 *
 
1105
 * Removes CDATA attributes from the special attribute table
 
1106
 */
 
1107
static void
 
1108
xmlCleanSpecialAttrCallback(void *payload, void *data,
 
1109
                            const xmlChar *fullname, const xmlChar *fullattr,
 
1110
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
 
1111
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
 
1112
 
 
1113
    if (((long) payload) == XML_ATTRIBUTE_CDATA) {
 
1114
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
 
1115
    }
 
1116
}
 
1117
 
 
1118
/**
 
1119
 * xmlCleanSpecialAttr:
 
1120
 * @ctxt:  an XML parser context
 
1121
 *
 
1122
 * Trim the list of attributes defined to remove all those of type
 
1123
 * CDATA as they are not special. This call should be done when finishing
 
1124
 * to parse the DTD and before starting to parse the document root.
 
1125
 */
 
1126
static void
 
1127
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
 
1128
{
 
1129
    if (ctxt->attsSpecial == NULL)
 
1130
        return;
 
1131
 
 
1132
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
 
1133
 
 
1134
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
 
1135
        xmlHashFree(ctxt->attsSpecial, NULL);
 
1136
        ctxt->attsSpecial = NULL;
 
1137
    }
 
1138
    return;
 
1139
}
 
1140
 
 
1141
/**
 
1142
 * xmlCheckLanguageID:
 
1143
 * @lang:  pointer to the string value
 
1144
 *
 
1145
 * Checks that the value conforms to the LanguageID production:
 
1146
 *
 
1147
 * NOTE: this is somewhat deprecated, those productions were removed from
 
1148
 *       the XML Second edition.
 
1149
 *
 
1150
 * [33] LanguageID ::= Langcode ('-' Subcode)*
 
1151
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
 
1152
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
 
1153
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
 
1154
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
 
1155
 * [38] Subcode ::= ([a-z] | [A-Z])+
 
1156
 *
 
1157
 * Returns 1 if correct 0 otherwise
 
1158
 **/
 
1159
int
 
1160
xmlCheckLanguageID(const xmlChar * lang)
 
1161
{
 
1162
    const xmlChar *cur = lang;
 
1163
 
 
1164
    if (cur == NULL)
 
1165
        return (0);
 
1166
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
 
1167
        ((cur[0] == 'I') && (cur[1] == '-'))) {
 
1168
        /*
 
1169
         * IANA code
 
1170
         */
 
1171
        cur += 2;
 
1172
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||  /* non input consuming */
 
1173
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
 
1174
            cur++;
 
1175
    } else if (((cur[0] == 'x') && (cur[1] == '-')) ||
 
1176
               ((cur[0] == 'X') && (cur[1] == '-'))) {
 
1177
        /*
 
1178
         * User code
 
1179
         */
 
1180
        cur += 2;
 
1181
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||  /* non input consuming */
 
1182
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
 
1183
            cur++;
 
1184
    } else if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
 
1185
               ((cur[0] >= 'a') && (cur[0] <= 'z'))) {
 
1186
        /*
 
1187
         * ISO639
 
1188
         */
 
1189
        cur++;
 
1190
        if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
 
1191
            ((cur[0] >= 'a') && (cur[0] <= 'z')))
 
1192
            cur++;
 
1193
        else
 
1194
            return (0);
 
1195
    } else
 
1196
        return (0);
 
1197
    while (cur[0] != 0) {       /* non input consuming */
 
1198
        if (cur[0] != '-')
 
1199
            return (0);
 
1200
        cur++;
 
1201
        if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
 
1202
            ((cur[0] >= 'a') && (cur[0] <= 'z')))
 
1203
            cur++;
 
1204
        else
 
1205
            return (0);
 
1206
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||  /* non input consuming */
 
1207
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
 
1208
            cur++;
 
1209
    }
 
1210
    return (1);
 
1211
}
 
1212
 
 
1213
/************************************************************************
 
1214
 *                                                                      *
 
1215
 *              Parser stacks related functions and macros              *
 
1216
 *                                                                      *
 
1217
 ************************************************************************/
 
1218
 
 
1219
xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
 
1220
                                     const xmlChar ** str);
 
1221
 
 
1222
#ifdef SAX2
 
1223
/**
 
1224
 * nsPush:
 
1225
 * @ctxt:  an XML parser context
 
1226
 * @prefix:  the namespace prefix or NULL
 
1227
 * @URL:  the namespace name
 
1228
 *
 
1229
 * Pushes a new parser namespace on top of the ns stack
 
1230
 *
 
1231
 * Returns -1 in case of error, -2 if the namespace should be discarded
 
1232
 *         and the index in the stack otherwise.
 
1233
 */
 
1234
static int
 
1235
nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
 
1236
{
 
1237
    if (ctxt->options & XML_PARSE_NSCLEAN) {
 
1238
        int i;
 
1239
        for (i = 0;i < ctxt->nsNr;i += 2) {
 
1240
            if (ctxt->nsTab[i] == prefix) {
 
1241
                /* in scope */
 
1242
                if (ctxt->nsTab[i + 1] == URL)
 
1243
                    return(-2);
 
1244
                /* out of scope keep it */
 
1245
                break;
 
1246
            }
 
1247
        }
 
1248
    }
 
1249
    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
 
1250
        ctxt->nsMax = 10;
 
1251
        ctxt->nsNr = 0;
 
1252
        ctxt->nsTab = (const xmlChar **)
 
1253
                      xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
 
1254
        if (ctxt->nsTab == NULL) {
 
1255
            xmlErrMemory(ctxt, NULL);
 
1256
            ctxt->nsMax = 0;
 
1257
            return (-1);
 
1258
        }
 
1259
    } else if (ctxt->nsNr >= ctxt->nsMax) {
 
1260
        const xmlChar ** tmp;
 
1261
        ctxt->nsMax *= 2;
 
1262
        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
 
1263
                                    ctxt->nsMax * sizeof(ctxt->nsTab[0]));
 
1264
        if (tmp == NULL) {
 
1265
            xmlErrMemory(ctxt, NULL);
 
1266
            ctxt->nsMax /= 2;
 
1267
            return (-1);
 
1268
        }
 
1269
        ctxt->nsTab = tmp;
 
1270
    }
 
1271
    ctxt->nsTab[ctxt->nsNr++] = prefix;
 
1272
    ctxt->nsTab[ctxt->nsNr++] = URL;
 
1273
    return (ctxt->nsNr);
 
1274
}
 
1275
/**
 
1276
 * nsPop:
 
1277
 * @ctxt: an XML parser context
 
1278
 * @nr:  the number to pop
 
1279
 *
 
1280
 * Pops the top @nr parser prefix/namespace from the ns stack
 
1281
 *
 
1282
 * Returns the number of namespaces removed
 
1283
 */
 
1284
static int
 
1285
nsPop(xmlParserCtxtPtr ctxt, int nr)
 
1286
{
 
1287
    int i;
 
1288
 
 
1289
    if (ctxt->nsTab == NULL) return(0);
 
1290
    if (ctxt->nsNr < nr) {
 
1291
        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
 
1292
        nr = ctxt->nsNr;
 
1293
    }
 
1294
    if (ctxt->nsNr <= 0)
 
1295
        return (0);
 
1296
    
 
1297
    for (i = 0;i < nr;i++) {
 
1298
         ctxt->nsNr--;
 
1299
         ctxt->nsTab[ctxt->nsNr] = NULL;
 
1300
    }
 
1301
    return(nr);
 
1302
}
 
1303
#endif
 
1304
 
 
1305
static int
 
1306
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
 
1307
    const xmlChar **atts;
 
1308
    int *attallocs;
 
1309
    int maxatts;
 
1310
 
 
1311
    if (ctxt->atts == NULL) {
 
1312
        maxatts = 55; /* allow for 10 attrs by default */
 
1313
        atts = (const xmlChar **)
 
1314
               xmlMalloc(maxatts * sizeof(xmlChar *));
 
1315
        if (atts == NULL) goto mem_error;
 
1316
        ctxt->atts = atts;
 
1317
        attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
 
1318
        if (attallocs == NULL) goto mem_error;
 
1319
        ctxt->attallocs = attallocs;
 
1320
        ctxt->maxatts = maxatts;
 
1321
    } else if (nr + 5 > ctxt->maxatts) {
 
1322
        maxatts = (nr + 5) * 2;
 
1323
        atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
 
1324
                                     maxatts * sizeof(const xmlChar *));
 
1325
        if (atts == NULL) goto mem_error;
 
1326
        ctxt->atts = atts;
 
1327
        attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
 
1328
                                     (maxatts / 5) * sizeof(int));
 
1329
        if (attallocs == NULL) goto mem_error;
 
1330
        ctxt->attallocs = attallocs;
 
1331
        ctxt->maxatts = maxatts;
 
1332
    }
 
1333
    return(ctxt->maxatts);
 
1334
mem_error:
 
1335
    xmlErrMemory(ctxt, NULL);
 
1336
    return(-1);
 
1337
}
 
1338
 
 
1339
/**
 
1340
 * inputPush:
 
1341
 * @ctxt:  an XML parser context
 
1342
 * @value:  the parser input
 
1343
 *
 
1344
 * Pushes a new parser input on top of the input stack
 
1345
 *
 
1346
 * Returns 0 in case of error, the index in the stack otherwise
 
1347
 */
 
1348
int
 
1349
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
 
1350
{
 
1351
    if ((ctxt == NULL) || (value == NULL))
 
1352
        return(0);
 
1353
    if (ctxt->inputNr >= ctxt->inputMax) {
 
1354
        ctxt->inputMax *= 2;
 
1355
        ctxt->inputTab =
 
1356
            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
 
1357
                                             ctxt->inputMax *
 
1358
                                             sizeof(ctxt->inputTab[0]));
 
1359
        if (ctxt->inputTab == NULL) {
 
1360
            xmlErrMemory(ctxt, NULL);
 
1361
            return (0);
 
1362
        }
 
1363
    }
 
1364
    ctxt->inputTab[ctxt->inputNr] = value;
 
1365
    ctxt->input = value;
 
1366
    return (ctxt->inputNr++);
 
1367
}
 
1368
/**
 
1369
 * inputPop:
 
1370
 * @ctxt: an XML parser context
 
1371
 *
 
1372
 * Pops the top parser input from the input stack
 
1373
 *
 
1374
 * Returns the input just removed
 
1375
 */
 
1376
xmlParserInputPtr
 
1377
inputPop(xmlParserCtxtPtr ctxt)
 
1378
{
 
1379
    xmlParserInputPtr ret;
 
1380
 
 
1381
    if (ctxt == NULL)
 
1382
        return(NULL);
 
1383
    if (ctxt->inputNr <= 0)
 
1384
        return (NULL);
 
1385
    ctxt->inputNr--;
 
1386
    if (ctxt->inputNr > 0)
 
1387
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
 
1388
    else
 
1389
        ctxt->input = NULL;
 
1390
    ret = ctxt->inputTab[ctxt->inputNr];
 
1391
    ctxt->inputTab[ctxt->inputNr] = NULL;
 
1392
    return (ret);
 
1393
}
 
1394
/**
 
1395
 * nodePush:
 
1396
 * @ctxt:  an XML parser context
 
1397
 * @value:  the element node
 
1398
 *
 
1399
 * Pushes a new element node on top of the node stack
 
1400
 *
 
1401
 * Returns 0 in case of error, the index in the stack otherwise
 
1402
 */
 
1403
int
 
1404
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
 
1405
{
 
1406
    if (ctxt == NULL) return(0);
 
1407
    if (ctxt->nodeNr >= ctxt->nodeMax) {
 
1408
        xmlNodePtr *tmp;
 
1409
 
 
1410
        tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
 
1411
                                      ctxt->nodeMax * 2 *
 
1412
                                      sizeof(ctxt->nodeTab[0]));
 
1413
        if (tmp == NULL) {
 
1414
            xmlErrMemory(ctxt, NULL);
 
1415
            return (0);
 
1416
        }
 
1417
        ctxt->nodeTab = tmp;
 
1418
        ctxt->nodeMax *= 2;
 
1419
    }
 
1420
    if (((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) {
 
1421
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
 
1422
                 "Excessive depth in document: change xmlParserMaxDepth = %d\n",
 
1423
                          xmlParserMaxDepth);
 
1424
        ctxt->instate = XML_PARSER_EOF;
 
1425
        return(0);
 
1426
    }
 
1427
    ctxt->nodeTab[ctxt->nodeNr] = value;
 
1428
    ctxt->node = value;
 
1429
    return (ctxt->nodeNr++);
 
1430
}
 
1431
/**
 
1432
 * nodePop:
 
1433
 * @ctxt: an XML parser context
 
1434
 *
 
1435
 * Pops the top element node from the node stack
 
1436
 *
 
1437
 * Returns the node just removed
 
1438
 */
 
1439
xmlNodePtr
 
1440
nodePop(xmlParserCtxtPtr ctxt)
 
1441
{
 
1442
    xmlNodePtr ret;
 
1443
 
 
1444
    if (ctxt == NULL) return(NULL);
 
1445
    if (ctxt->nodeNr <= 0)
 
1446
        return (NULL);
 
1447
    ctxt->nodeNr--;
 
1448
    if (ctxt->nodeNr > 0)
 
1449
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
 
1450
    else
 
1451
        ctxt->node = NULL;
 
1452
    ret = ctxt->nodeTab[ctxt->nodeNr];
 
1453
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
 
1454
    return (ret);
 
1455
}
 
1456
 
 
1457
#ifdef LIBXML_PUSH_ENABLED
 
1458
/**
 
1459
 * nameNsPush:
 
1460
 * @ctxt:  an XML parser context
 
1461
 * @value:  the element name
 
1462
 * @prefix:  the element prefix
 
1463
 * @URI:  the element namespace name
 
1464
 *
 
1465
 * Pushes a new element name/prefix/URL on top of the name stack
 
1466
 *
 
1467
 * Returns -1 in case of error, the index in the stack otherwise
 
1468
 */
 
1469
static int
 
1470
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
 
1471
           const xmlChar *prefix, const xmlChar *URI, int nsNr)
 
1472
{
 
1473
    if (ctxt->nameNr >= ctxt->nameMax) {
 
1474
        const xmlChar * *tmp;
 
1475
        void **tmp2;
 
1476
        ctxt->nameMax *= 2;
 
1477
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
 
1478
                                    ctxt->nameMax *
 
1479
                                    sizeof(ctxt->nameTab[0]));
 
1480
        if (tmp == NULL) {
 
1481
            ctxt->nameMax /= 2;
 
1482
            goto mem_error;
 
1483
        }
 
1484
        ctxt->nameTab = tmp;
 
1485
        tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
 
1486
                                    ctxt->nameMax * 3 *
 
1487
                                    sizeof(ctxt->pushTab[0]));
 
1488
        if (tmp2 == NULL) {
 
1489
            ctxt->nameMax /= 2;
 
1490
            goto mem_error;
 
1491
        }
 
1492
        ctxt->pushTab = tmp2;
 
1493
    }
 
1494
    ctxt->nameTab[ctxt->nameNr] = value;
 
1495
    ctxt->name = value;
 
1496
    ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
 
1497
    ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
 
1498
    ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
 
1499
    return (ctxt->nameNr++);
 
1500
mem_error:
 
1501
    xmlErrMemory(ctxt, NULL);
 
1502
    return (-1);
 
1503
}
 
1504
/**
 
1505
 * nameNsPop:
 
1506
 * @ctxt: an XML parser context
 
1507
 *
 
1508
 * Pops the top element/prefix/URI name from the name stack
 
1509
 *
 
1510
 * Returns the name just removed
 
1511
 */
 
1512
static const xmlChar *
 
1513
nameNsPop(xmlParserCtxtPtr ctxt)
 
1514
{
 
1515
    const xmlChar *ret;
 
1516
 
 
1517
    if (ctxt->nameNr <= 0)
 
1518
        return (NULL);
 
1519
    ctxt->nameNr--;
 
1520
    if (ctxt->nameNr > 0)
 
1521
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
 
1522
    else
 
1523
        ctxt->name = NULL;
 
1524
    ret = ctxt->nameTab[ctxt->nameNr];
 
1525
    ctxt->nameTab[ctxt->nameNr] = NULL;
 
1526
    return (ret);
 
1527
}
 
1528
#endif /* LIBXML_PUSH_ENABLED */
 
1529
 
 
1530
/**
 
1531
 * namePush:
 
1532
 * @ctxt:  an XML parser context
 
1533
 * @value:  the element name
 
1534
 *
 
1535
 * Pushes a new element name on top of the name stack
 
1536
 *
 
1537
 * Returns -1 in case of error, the index in the stack otherwise
 
1538
 */
 
1539
int
 
1540
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
 
1541
{
 
1542
    if (ctxt == NULL) return (-1);
 
1543
 
 
1544
    if (ctxt->nameNr >= ctxt->nameMax) {
 
1545
        const xmlChar * *tmp;
 
1546
        ctxt->nameMax *= 2;
 
1547
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
 
1548
                                    ctxt->nameMax *
 
1549
                                    sizeof(ctxt->nameTab[0]));
 
1550
        if (tmp == NULL) {
 
1551
            ctxt->nameMax /= 2;
 
1552
            goto mem_error;
 
1553
        }
 
1554
        ctxt->nameTab = tmp;
 
1555
    }
 
1556
    ctxt->nameTab[ctxt->nameNr] = value;
 
1557
    ctxt->name = value;
 
1558
    return (ctxt->nameNr++);
 
1559
mem_error:
 
1560
    xmlErrMemory(ctxt, NULL);
 
1561
    return (-1);
 
1562
}
 
1563
/**
 
1564
 * namePop:
 
1565
 * @ctxt: an XML parser context
 
1566
 *
 
1567
 * Pops the top element name from the name stack
 
1568
 *
 
1569
 * Returns the name just removed
 
1570
 */
 
1571
const xmlChar *
 
1572
namePop(xmlParserCtxtPtr ctxt)
 
1573
{
 
1574
    const xmlChar *ret;
 
1575
 
 
1576
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
 
1577
        return (NULL);
 
1578
    ctxt->nameNr--;
 
1579
    if (ctxt->nameNr > 0)
 
1580
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
 
1581
    else
 
1582
        ctxt->name = NULL;
 
1583
    ret = ctxt->nameTab[ctxt->nameNr];
 
1584
    ctxt->nameTab[ctxt->nameNr] = NULL;
 
1585
    return (ret);
 
1586
}
 
1587
 
 
1588
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
 
1589
    if (ctxt->spaceNr >= ctxt->spaceMax) {
 
1590
        int *tmp;
 
1591
 
 
1592
        ctxt->spaceMax *= 2;
 
1593
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
 
1594
                                 ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
 
1595
        if (tmp == NULL) {
 
1596
            xmlErrMemory(ctxt, NULL);
 
1597
            return(0);
 
1598
        }
 
1599
        ctxt->spaceTab = tmp;
 
1600
    }
 
1601
    ctxt->spaceTab[ctxt->spaceNr] = val;
 
1602
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
 
1603
    return(ctxt->spaceNr++);
 
1604
}
 
1605
 
 
1606
static int spacePop(xmlParserCtxtPtr ctxt) {
 
1607
    int ret;
 
1608
    if (ctxt->spaceNr <= 0) return(0);
 
1609
    ctxt->spaceNr--;
 
1610
    if (ctxt->spaceNr > 0)
 
1611
        ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
 
1612
    else
 
1613
        ctxt->space = &ctxt->spaceTab[0];
 
1614
    ret = ctxt->spaceTab[ctxt->spaceNr];
 
1615
    ctxt->spaceTab[ctxt->spaceNr] = -1;
 
1616
    return(ret);
 
1617
}
 
1618
 
 
1619
/*
 
1620
 * Macros for accessing the content. Those should be used only by the parser,
 
1621
 * and not exported.
 
1622
 *
 
1623
 * Dirty macros, i.e. one often need to make assumption on the context to
 
1624
 * use them
 
1625
 *
 
1626
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
 
1627
 *           To be used with extreme caution since operations consuming
 
1628
 *           characters may move the input buffer to a different location !
 
1629
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
 
1630
 *           This should be used internally by the parser
 
1631
 *           only to compare to ASCII values otherwise it would break when
 
1632
 *           running with UTF-8 encoding.
 
1633
 *   RAW     same as CUR but in the input buffer, bypass any token
 
1634
 *           extraction that may have been done
 
1635
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
 
1636
 *           to compare on ASCII based substring.
 
1637
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
 
1638
 *           strings without newlines within the parser.
 
1639
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII 
 
1640
 *           defined char within the parser.
 
1641
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
 
1642
 *
 
1643
 *   NEXT    Skip to the next character, this does the proper decoding
 
1644
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
 
1645
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
 
1646
 *   CUR_CHAR(l) returns the current unicode character (int), set l
 
1647
 *           to the number of xmlChars used for the encoding [0-5].
 
1648
 *   CUR_SCHAR  same but operate on a string instead of the context
 
1649
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
 
1650
 *            the index
 
1651
 *   GROW, SHRINK  handling of input buffers
 
1652
 */
 
1653
 
 
1654
#define RAW (*ctxt->input->cur)
 
1655
#define CUR (*ctxt->input->cur)
 
1656
#define NXT(val) ctxt->input->cur[(val)]
 
1657
#define CUR_PTR ctxt->input->cur
 
1658
 
 
1659
#define CMP4( s, c1, c2, c3, c4 ) \
 
1660
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
 
1661
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
 
1662
#define CMP5( s, c1, c2, c3, c4, c5 ) \
 
1663
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
 
1664
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
 
1665
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
 
1666
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
 
1667
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
 
1668
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
 
1669
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
 
1670
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
 
1671
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
 
1672
    ((unsigned char *) s)[ 8 ] == c9 )
 
1673
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
 
1674
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
 
1675
    ((unsigned char *) s)[ 9 ] == c10 )
 
1676
 
 
1677
#define SKIP(val) do {                                                  \
 
1678
    ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);                   \
 
1679
    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
 
1680
    if ((*ctxt->input->cur == 0) &&                                     \
 
1681
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
 
1682
            xmlPopInput(ctxt);                                          \
 
1683
  } while (0)
 
1684
 
 
1685
#define SKIPL(val) do {                                                 \
 
1686
    int skipl;                                                          \
 
1687
    for(skipl=0; skipl<val; skipl++) {                                  \
 
1688
        if (*(ctxt->input->cur) == '\n') {                              \
 
1689
        ctxt->input->line++; ctxt->input->col = 1;                      \
 
1690
        } else ctxt->input->col++;                                      \
 
1691
        ctxt->nbChars++;                                                \
 
1692
        ctxt->input->cur++;                                             \
 
1693
    }                                                                   \
 
1694
    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
 
1695
    if ((*ctxt->input->cur == 0) &&                                     \
 
1696
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
 
1697
            xmlPopInput(ctxt);                                          \
 
1698
  } while (0)
 
1699
 
 
1700
#define SHRINK if ((ctxt->progressive == 0) &&                          \
 
1701
                   (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
 
1702
                   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
 
1703
        xmlSHRINK (ctxt);
 
1704
 
 
1705
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
 
1706
    xmlParserInputShrink(ctxt->input);
 
1707
    if ((*ctxt->input->cur == 0) &&
 
1708
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 
1709
            xmlPopInput(ctxt);
 
1710
  }
 
1711
 
 
1712
#define GROW if ((ctxt->progressive == 0) &&                            \
 
1713
                 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
 
1714
        xmlGROW (ctxt);
 
1715
 
 
1716
static void xmlGROW (xmlParserCtxtPtr ctxt) {
 
1717
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
 
1718
    if ((*ctxt->input->cur == 0) &&
 
1719
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 
1720
            xmlPopInput(ctxt);
 
1721
}
 
1722
 
 
1723
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
 
1724
 
 
1725
#define NEXT xmlNextChar(ctxt)
 
1726
 
 
1727
#define NEXT1 {                                                         \
 
1728
        ctxt->input->col++;                                             \
 
1729
        ctxt->input->cur++;                                             \
 
1730
        ctxt->nbChars++;                                                \
 
1731
        if (*ctxt->input->cur == 0)                                     \
 
1732
            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);               \
 
1733
    }
 
1734
 
 
1735
#define NEXTL(l) do {                                                   \
 
1736
    if (*(ctxt->input->cur) == '\n') {                                  \
 
1737
        ctxt->input->line++; ctxt->input->col = 1;                      \
 
1738
    } else ctxt->input->col++;                                          \
 
1739
    ctxt->input->cur += l;                              \
 
1740
    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
 
1741
  } while (0)
 
1742
 
 
1743
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
 
1744
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
 
1745
 
 
1746
#define COPY_BUF(l,b,i,v)                                               \
 
1747
    if (l == 1) b[i++] = (xmlChar) v;                                   \
 
1748
    else i += xmlCopyCharMultiByte(&b[i],v)
 
1749
 
 
1750
/**
 
1751
 * xmlSkipBlankChars:
 
1752
 * @ctxt:  the XML parser context
 
1753
 *
 
1754
 * skip all blanks character found at that point in the input streams.
 
1755
 * It pops up finished entities in the process if allowable at that point.
 
1756
 *
 
1757
 * Returns the number of space chars skipped
 
1758
 */
 
1759
 
 
1760
int
 
1761
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
 
1762
    int res = 0;
 
1763
 
 
1764
    /*
 
1765
     * It's Okay to use CUR/NEXT here since all the blanks are on
 
1766
     * the ASCII range.
 
1767
     */
 
1768
    if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
 
1769
        const xmlChar *cur;
 
1770
        /*
 
1771
         * if we are in the document content, go really fast
 
1772
         */
 
1773
        cur = ctxt->input->cur;
 
1774
        while (IS_BLANK_CH(*cur)) {
 
1775
            if (*cur == '\n') {
 
1776
                ctxt->input->line++; ctxt->input->col = 1;
 
1777
            }
 
1778
            cur++;
 
1779
            res++;
 
1780
            if (*cur == 0) {
 
1781
                ctxt->input->cur = cur;
 
1782
                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
 
1783
                cur = ctxt->input->cur;
 
1784
            }
 
1785
        }
 
1786
        ctxt->input->cur = cur;
 
1787
    } else {
 
1788
        int cur;
 
1789
        do {
 
1790
            cur = CUR;
 
1791
            while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
 
1792
                NEXT;
 
1793
                cur = CUR;
 
1794
                res++;
 
1795
            }
 
1796
            while ((cur == 0) && (ctxt->inputNr > 1) &&
 
1797
                   (ctxt->instate != XML_PARSER_COMMENT)) {
 
1798
                xmlPopInput(ctxt);
 
1799
                cur = CUR;
 
1800
            }
 
1801
            /*
 
1802
             * Need to handle support of entities branching here
 
1803
             */
 
1804
            if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
 
1805
        } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
 
1806
    }
 
1807
    return(res);
 
1808
}
 
1809
 
 
1810
/************************************************************************
 
1811
 *                                                                      *
 
1812
 *              Commodity functions to handle entities                  *
 
1813
 *                                                                      *
 
1814
 ************************************************************************/
 
1815
 
 
1816
/**
 
1817
 * xmlPopInput:
 
1818
 * @ctxt:  an XML parser context
 
1819
 *
 
1820
 * xmlPopInput: the current input pointed by ctxt->input came to an end
 
1821
 *          pop it and return the next char.
 
1822
 *
 
1823
 * Returns the current xmlChar in the parser context
 
1824
 */
 
1825
xmlChar
 
1826
xmlPopInput(xmlParserCtxtPtr ctxt) {
 
1827
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
 
1828
    if (xmlParserDebugEntities)
 
1829
        xmlGenericError(xmlGenericErrorContext,
 
1830
                "Popping input %d\n", ctxt->inputNr);
 
1831
    xmlFreeInputStream(inputPop(ctxt));
 
1832
    if ((*ctxt->input->cur == 0) &&
 
1833
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 
1834
            return(xmlPopInput(ctxt));
 
1835
    return(CUR);
 
1836
}
 
1837
 
 
1838
/**
 
1839
 * xmlPushInput:
 
1840
 * @ctxt:  an XML parser context
 
1841
 * @input:  an XML parser input fragment (entity, XML fragment ...).
 
1842
 *
 
1843
 * xmlPushInput: switch to a new input stream which is stacked on top
 
1844
 *               of the previous one(s).
 
1845
 */
 
1846
void
 
1847
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
 
1848
    if (input == NULL) return;
 
1849
 
 
1850
    if (xmlParserDebugEntities) {
 
1851
        if ((ctxt->input != NULL) && (ctxt->input->filename))
 
1852
            xmlGenericError(xmlGenericErrorContext,
 
1853
                    "%s(%d): ", ctxt->input->filename,
 
1854
                    ctxt->input->line);
 
1855
        xmlGenericError(xmlGenericErrorContext,
 
1856
                "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
 
1857
    }
 
1858
    inputPush(ctxt, input);
 
1859
    GROW;
 
1860
}
 
1861
 
 
1862
/**
 
1863
 * xmlParseCharRef:
 
1864
 * @ctxt:  an XML parser context
 
1865
 *
 
1866
 * parse Reference declarations
 
1867
 *
 
1868
 * [66] CharRef ::= '&#' [0-9]+ ';' |
 
1869
 *                  '&#x' [0-9a-fA-F]+ ';'
 
1870
 *
 
1871
 * [ WFC: Legal Character ]
 
1872
 * Characters referred to using character references must match the
 
1873
 * production for Char. 
 
1874
 *
 
1875
 * Returns the value parsed (as an int), 0 in case of error
 
1876
 */
 
1877
int
 
1878
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
 
1879
    unsigned int val = 0;
 
1880
    int count = 0;
 
1881
    unsigned int outofrange = 0;
 
1882
 
 
1883
    /*
 
1884
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
 
1885
     */
 
1886
    if ((RAW == '&') && (NXT(1) == '#') &&
 
1887
        (NXT(2) == 'x')) {
 
1888
        SKIP(3);
 
1889
        GROW;
 
1890
        while (RAW != ';') { /* loop blocked by count */
 
1891
            if (count++ > 20) {
 
1892
                count = 0;
 
1893
                GROW;
 
1894
            }
 
1895
            if ((RAW >= '0') && (RAW <= '9')) 
 
1896
                val = val * 16 + (CUR - '0');
 
1897
            else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
 
1898
                val = val * 16 + (CUR - 'a') + 10;
 
1899
            else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
 
1900
                val = val * 16 + (CUR - 'A') + 10;
 
1901
            else {
 
1902
                xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
 
1903
                val = 0;
 
1904
                break;
 
1905
            }
 
1906
            if (val > 0x10FFFF)
 
1907
                outofrange = val;
 
1908
 
 
1909
            NEXT;
 
1910
            count++;
 
1911
        }
 
1912
        if (RAW == ';') {
 
1913
            /* on purpose to avoid reentrancy problems with NEXT and SKIP */
 
1914
            ctxt->input->col++;
 
1915
            ctxt->nbChars ++;
 
1916
            ctxt->input->cur++;
 
1917
        }
 
1918
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
 
1919
        SKIP(2);
 
1920
        GROW;
 
1921
        while (RAW != ';') { /* loop blocked by count */
 
1922
            if (count++ > 20) {
 
1923
                count = 0;
 
1924
                GROW;
 
1925
            }
 
1926
            if ((RAW >= '0') && (RAW <= '9')) 
 
1927
                val = val * 10 + (CUR - '0');
 
1928
            else {
 
1929
                xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
 
1930
                val = 0;
 
1931
                break;
 
1932
            }
 
1933
            if (val > 0x10FFFF)
 
1934
                outofrange = val;
 
1935
 
 
1936
            NEXT;
 
1937
            count++;
 
1938
        }
 
1939
        if (RAW == ';') {
 
1940
            /* on purpose to avoid reentrancy problems with NEXT and SKIP */
 
1941
            ctxt->input->col++;
 
1942
            ctxt->nbChars ++;
 
1943
            ctxt->input->cur++;
 
1944
        }
 
1945
    } else {
 
1946
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
 
1947
    }
 
1948
 
 
1949
    /*
 
1950
     * [ WFC: Legal Character ]
 
1951
     * Characters referred to using character references must match the
 
1952
     * production for Char. 
 
1953
     */
 
1954
    if ((IS_CHAR(val) && (outofrange == 0))) {
 
1955
        return(val);
 
1956
    } else {
 
1957
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
1958
                          "xmlParseCharRef: invalid xmlChar value %d\n",
 
1959
                          val);
 
1960
    }
 
1961
    return(0);
 
1962
}
 
1963
 
 
1964
/**
 
1965
 * xmlParseStringCharRef:
 
1966
 * @ctxt:  an XML parser context
 
1967
 * @str:  a pointer to an index in the string
 
1968
 *
 
1969
 * parse Reference declarations, variant parsing from a string rather
 
1970
 * than an an input flow.
 
1971
 *
 
1972
 * [66] CharRef ::= '&#' [0-9]+ ';' |
 
1973
 *                  '&#x' [0-9a-fA-F]+ ';'
 
1974
 *
 
1975
 * [ WFC: Legal Character ]
 
1976
 * Characters referred to using character references must match the
 
1977
 * production for Char. 
 
1978
 *
 
1979
 * Returns the value parsed (as an int), 0 in case of error, str will be
 
1980
 *         updated to the current value of the index
 
1981
 */
 
1982
static int
 
1983
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 
1984
    const xmlChar *ptr;
 
1985
    xmlChar cur;
 
1986
    unsigned int val = 0;
 
1987
    unsigned int outofrange = 0;
 
1988
 
 
1989
    if ((str == NULL) || (*str == NULL)) return(0);
 
1990
    ptr = *str;
 
1991
    cur = *ptr;
 
1992
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
 
1993
        ptr += 3;
 
1994
        cur = *ptr;
 
1995
        while (cur != ';') { /* Non input consuming loop */
 
1996
            if ((cur >= '0') && (cur <= '9')) 
 
1997
                val = val * 16 + (cur - '0');
 
1998
            else if ((cur >= 'a') && (cur <= 'f'))
 
1999
                val = val * 16 + (cur - 'a') + 10;
 
2000
            else if ((cur >= 'A') && (cur <= 'F'))
 
2001
                val = val * 16 + (cur - 'A') + 10;
 
2002
            else {
 
2003
                xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
 
2004
                val = 0;
 
2005
                break;
 
2006
            }
 
2007
            if (val > 0x10FFFF)
 
2008
                outofrange = val;
 
2009
 
 
2010
            ptr++;
 
2011
            cur = *ptr;
 
2012
        }
 
2013
        if (cur == ';')
 
2014
            ptr++;
 
2015
    } else if  ((cur == '&') && (ptr[1] == '#')){
 
2016
        ptr += 2;
 
2017
        cur = *ptr;
 
2018
        while (cur != ';') { /* Non input consuming loops */
 
2019
            if ((cur >= '0') && (cur <= '9')) 
 
2020
                val = val * 10 + (cur - '0');
 
2021
            else {
 
2022
                xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
 
2023
                val = 0;
 
2024
                break;
 
2025
            }
 
2026
            if (val > 0x10FFFF)
 
2027
                outofrange = val;
 
2028
 
 
2029
            ptr++;
 
2030
            cur = *ptr;
 
2031
        }
 
2032
        if (cur == ';')
 
2033
            ptr++;
 
2034
    } else {
 
2035
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
 
2036
        return(0);
 
2037
    }
 
2038
    *str = ptr;
 
2039
 
 
2040
    /*
 
2041
     * [ WFC: Legal Character ]
 
2042
     * Characters referred to using character references must match the
 
2043
     * production for Char. 
 
2044
     */
 
2045
    if ((IS_CHAR(val) && (outofrange == 0))) {
 
2046
        return(val);
 
2047
    } else {
 
2048
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
2049
                          "xmlParseStringCharRef: invalid xmlChar value %d\n",
 
2050
                          val);
 
2051
    }
 
2052
    return(0);
 
2053
}
 
2054
 
 
2055
/**
 
2056
 * xmlNewBlanksWrapperInputStream:
 
2057
 * @ctxt:  an XML parser context
 
2058
 * @entity:  an Entity pointer
 
2059
 *
 
2060
 * Create a new input stream for wrapping
 
2061
 * blanks around a PEReference
 
2062
 *
 
2063
 * Returns the new input stream or NULL
 
2064
 */
 
2065
 
 
2066
static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
 
2067
 
 
2068
static xmlParserInputPtr
 
2069
xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
 
2070
    xmlParserInputPtr input;
 
2071
    xmlChar *buffer;
 
2072
    size_t length;
 
2073
    if (entity == NULL) {
 
2074
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
2075
                    "xmlNewBlanksWrapperInputStream entity\n");
 
2076
        return(NULL);
 
2077
    }
 
2078
    if (xmlParserDebugEntities)
 
2079
        xmlGenericError(xmlGenericErrorContext,
 
2080
                "new blanks wrapper for entity: %s\n", entity->name);
 
2081
    input = xmlNewInputStream(ctxt);
 
2082
    if (input == NULL) {
 
2083
        return(NULL);
 
2084
    }
 
2085
    length = xmlStrlen(entity->name) + 5;
 
2086
    buffer = xmlMallocAtomic(length);
 
2087
    if (buffer == NULL) {
 
2088
        xmlErrMemory(ctxt, NULL);
 
2089
        xmlFree(input);
 
2090
        return(NULL);
 
2091
    }
 
2092
    buffer [0] = ' ';
 
2093
    buffer [1] = '%';
 
2094
    buffer [length-3] = ';';
 
2095
    buffer [length-2] = ' ';
 
2096
    buffer [length-1] = 0;
 
2097
    memcpy(buffer + 2, entity->name, length - 5);
 
2098
    input->free = deallocblankswrapper;
 
2099
    input->base = buffer;
 
2100
    input->cur = buffer;
 
2101
    input->length = length;
 
2102
    input->end = &buffer[length];
 
2103
    return(input);
 
2104
}
 
2105
 
 
2106
/**
 
2107
 * xmlParserHandlePEReference:
 
2108
 * @ctxt:  the parser context
 
2109
 * 
 
2110
 * [69] PEReference ::= '%' Name ';'
 
2111
 *
 
2112
 * [ WFC: No Recursion ]
 
2113
 * A parsed entity must not contain a recursive
 
2114
 * reference to itself, either directly or indirectly. 
 
2115
 *
 
2116
 * [ WFC: Entity Declared ]
 
2117
 * In a document without any DTD, a document with only an internal DTD
 
2118
 * subset which contains no parameter entity references, or a document
 
2119
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
2120
 * entity must precede any reference to it...
 
2121
 *
 
2122
 * [ VC: Entity Declared ]
 
2123
 * In a document with an external subset or external parameter entities
 
2124
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
2125
 * must precede any reference to it...
 
2126
 *
 
2127
 * [ WFC: In DTD ]
 
2128
 * Parameter-entity references may only appear in the DTD.
 
2129
 * NOTE: misleading but this is handled.
 
2130
 *
 
2131
 * A PEReference may have been detected in the current input stream
 
2132
 * the handling is done accordingly to 
 
2133
 *      http://www.w3.org/TR/REC-xml#entproc
 
2134
 * i.e. 
 
2135
 *   - Included in literal in entity values
 
2136
 *   - Included as Parameter Entity reference within DTDs
 
2137
 */
 
2138
void
 
2139
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
 
2140
    const xmlChar *name;
 
2141
    xmlEntityPtr entity = NULL;
 
2142
    xmlParserInputPtr input;
 
2143
 
 
2144
    if (RAW != '%') return;
 
2145
    switch(ctxt->instate) {
 
2146
        case XML_PARSER_CDATA_SECTION:
 
2147
            return;
 
2148
        case XML_PARSER_COMMENT:
 
2149
            return;
 
2150
        case XML_PARSER_START_TAG:
 
2151
            return;
 
2152
        case XML_PARSER_END_TAG:
 
2153
            return;
 
2154
        case XML_PARSER_EOF:
 
2155
            xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
 
2156
            return;
 
2157
        case XML_PARSER_PROLOG:
 
2158
        case XML_PARSER_START:
 
2159
        case XML_PARSER_MISC:
 
2160
            xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
 
2161
            return;
 
2162
        case XML_PARSER_ENTITY_DECL:
 
2163
        case XML_PARSER_CONTENT:
 
2164
        case XML_PARSER_ATTRIBUTE_VALUE:
 
2165
        case XML_PARSER_PI:
 
2166
        case XML_PARSER_SYSTEM_LITERAL:
 
2167
        case XML_PARSER_PUBLIC_LITERAL:
 
2168
            /* we just ignore it there */
 
2169
            return;
 
2170
        case XML_PARSER_EPILOG:
 
2171
            xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
 
2172
            return;
 
2173
        case XML_PARSER_ENTITY_VALUE:
 
2174
            /*
 
2175
             * NOTE: in the case of entity values, we don't do the
 
2176
             *       substitution here since we need the literal
 
2177
             *       entity value to be able to save the internal
 
2178
             *       subset of the document.
 
2179
             *       This will be handled by xmlStringDecodeEntities
 
2180
             */
 
2181
            return;
 
2182
        case XML_PARSER_DTD:
 
2183
            /*
 
2184
             * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
 
2185
             * In the internal DTD subset, parameter-entity references
 
2186
             * can occur only where markup declarations can occur, not
 
2187
             * within markup declarations.
 
2188
             * In that case this is handled in xmlParseMarkupDecl
 
2189
             */
 
2190
            if ((ctxt->external == 0) && (ctxt->inputNr == 1))
 
2191
                return;
 
2192
            if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
 
2193
                return;
 
2194
            break;
 
2195
        case XML_PARSER_IGNORE:
 
2196
            return;
 
2197
    }
 
2198
 
 
2199
    NEXT;
 
2200
    name = xmlParseName(ctxt);
 
2201
    if (xmlParserDebugEntities)
 
2202
        xmlGenericError(xmlGenericErrorContext,
 
2203
                "PEReference: %s\n", name);
 
2204
    if (name == NULL) {
 
2205
        xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
 
2206
    } else {
 
2207
        if (RAW == ';') {
 
2208
            NEXT;
 
2209
            if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
 
2210
                entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
2211
            if (entity == NULL) {
 
2212
                
 
2213
                /*
 
2214
                 * [ WFC: Entity Declared ]
 
2215
                 * In a document without any DTD, a document with only an
 
2216
                 * internal DTD subset which contains no parameter entity
 
2217
                 * references, or a document with "standalone='yes'", ...
 
2218
                 * ... The declaration of a parameter entity must precede
 
2219
                 * any reference to it...
 
2220
                 */
 
2221
                if ((ctxt->standalone == 1) ||
 
2222
                    ((ctxt->hasExternalSubset == 0) &&
 
2223
                     (ctxt->hasPErefs == 0))) {
 
2224
                    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
2225
                         "PEReference: %%%s; not found\n", name);
 
2226
                } else {
 
2227
                    /*
 
2228
                     * [ VC: Entity Declared ]
 
2229
                     * In a document with an external subset or external
 
2230
                     * parameter entities with "standalone='no'", ...
 
2231
                     * ... The declaration of a parameter entity must precede
 
2232
                     * any reference to it...
 
2233
                     */
 
2234
                    if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
 
2235
                        xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
2236
                                         "PEReference: %%%s; not found\n",
 
2237
                                         name);
 
2238
                    } else 
 
2239
                        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
2240
                                      "PEReference: %%%s; not found\n",
 
2241
                                      name, NULL);
 
2242
                    ctxt->valid = 0;
 
2243
                }
 
2244
            } else if (ctxt->input->free != deallocblankswrapper) {
 
2245
                    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
 
2246
                    xmlPushInput(ctxt, input);
 
2247
            } else {
 
2248
                if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
 
2249
                    (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
 
2250
                    xmlChar start[4];
 
2251
                    xmlCharEncoding enc;
 
2252
 
 
2253
                    /*
 
2254
                     * handle the extra spaces added before and after
 
2255
                     * c.f. http://www.w3.org/TR/REC-xml#as-PE
 
2256
                     * this is done independently.
 
2257
                     */
 
2258
                    input = xmlNewEntityInputStream(ctxt, entity);
 
2259
                    xmlPushInput(ctxt, input);
 
2260
 
 
2261
                    /* 
 
2262
                     * Get the 4 first bytes and decode the charset
 
2263
                     * if enc != XML_CHAR_ENCODING_NONE
 
2264
                     * plug some encoding conversion routines.
 
2265
                     * Note that, since we may have some non-UTF8
 
2266
                     * encoding (like UTF16, bug 135229), the 'length'
 
2267
                     * is not known, but we can calculate based upon
 
2268
                     * the amount of data in the buffer.
 
2269
                     */
 
2270
                    GROW
 
2271
                    if ((ctxt->input->end - ctxt->input->cur)>=4) {
 
2272
                        start[0] = RAW;
 
2273
                        start[1] = NXT(1);
 
2274
                        start[2] = NXT(2);
 
2275
                        start[3] = NXT(3);
 
2276
                        enc = xmlDetectCharEncoding(start, 4);
 
2277
                        if (enc != XML_CHAR_ENCODING_NONE) {
 
2278
                            xmlSwitchEncoding(ctxt, enc);
 
2279
                        }
 
2280
                    }
 
2281
 
 
2282
                    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
2283
                        (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
 
2284
                        (IS_BLANK_CH(NXT(5)))) {
 
2285
                        xmlParseTextDecl(ctxt);
 
2286
                    }
 
2287
                } else {
 
2288
                    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
2289
                             "PEReference: %s is not a parameter entity\n",
 
2290
                                      name);
 
2291
                }
 
2292
            }
 
2293
        } else {
 
2294
            xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
 
2295
        }
 
2296
    }
 
2297
}
 
2298
 
 
2299
/*
 
2300
 * Macro used to grow the current buffer.
 
2301
 */
 
2302
#define growBuffer(buffer) {                                            \
 
2303
    xmlChar *tmp;                                                       \
 
2304
    buffer##_size *= 2;                                                 \
 
2305
    tmp = (xmlChar *)                                                   \
 
2306
                xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
 
2307
    if (tmp == NULL) goto mem_error;                                    \
 
2308
    buffer = tmp;                                                       \
 
2309
}
 
2310
 
 
2311
/**
 
2312
 * xmlStringLenDecodeEntities:
 
2313
 * @ctxt:  the parser context
 
2314
 * @str:  the input string
 
2315
 * @len: the string length
 
2316
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
 
2317
 * @end:  an end marker xmlChar, 0 if none
 
2318
 * @end2:  an end marker xmlChar, 0 if none
 
2319
 * @end3:  an end marker xmlChar, 0 if none
 
2320
 * 
 
2321
 * Takes a entity string content and process to do the adequate substitutions.
 
2322
 *
 
2323
 * [67] Reference ::= EntityRef | CharRef
 
2324
 *
 
2325
 * [69] PEReference ::= '%' Name ';'
 
2326
 *
 
2327
 * Returns A newly allocated string with the substitution done. The caller
 
2328
 *      must deallocate it !
 
2329
 */
 
2330
xmlChar *
 
2331
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
 
2332
                      int what, xmlChar end, xmlChar  end2, xmlChar end3) {
 
2333
    xmlChar *buffer = NULL;
 
2334
    int buffer_size = 0;
 
2335
 
 
2336
    xmlChar *current = NULL;
 
2337
    xmlChar *rep = NULL;
 
2338
    const xmlChar *last;
 
2339
    xmlEntityPtr ent;
 
2340
    int c,l;
 
2341
    int nbchars = 0;
 
2342
 
 
2343
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
 
2344
        return(NULL);
 
2345
    last = str + len;
 
2346
 
 
2347
    if (ctxt->depth > 40) {
 
2348
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
2349
        return(NULL);
 
2350
    }
 
2351
 
 
2352
    /*
 
2353
     * allocate a translation buffer.
 
2354
     */
 
2355
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
 
2356
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
 
2357
    if (buffer == NULL) goto mem_error;
 
2358
 
 
2359
    /*
 
2360
     * OK loop until we reach one of the ending char or a size limit.
 
2361
     * we are operating on already parsed values.
 
2362
     */
 
2363
    if (str < last)
 
2364
        c = CUR_SCHAR(str, l);
 
2365
    else
 
2366
        c = 0;
 
2367
    while ((c != 0) && (c != end) && /* non input consuming loop */
 
2368
           (c != end2) && (c != end3)) {
 
2369
 
 
2370
        if (c == 0) break;
 
2371
        if ((c == '&') && (str[1] == '#')) {
 
2372
            int val = xmlParseStringCharRef(ctxt, &str);
 
2373
            if (val != 0) {
 
2374
                COPY_BUF(0,buffer,nbchars,val);
 
2375
            }
 
2376
            if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
 
2377
                growBuffer(buffer);
 
2378
            }
 
2379
        } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
 
2380
            if (xmlParserDebugEntities)
 
2381
                xmlGenericError(xmlGenericErrorContext,
 
2382
                        "String decoding Entity Reference: %.30s\n",
 
2383
                        str);
 
2384
            ent = xmlParseStringEntityRef(ctxt, &str);
 
2385
            if ((ent != NULL) &&
 
2386
                (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
2387
                if (ent->content != NULL) {
 
2388
                    COPY_BUF(0,buffer,nbchars,ent->content[0]);
 
2389
                    if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
 
2390
                        growBuffer(buffer);
 
2391
                    }
 
2392
                } else {
 
2393
                    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
 
2394
                            "predefined entity has no content\n");
 
2395
                }
 
2396
            } else if ((ent != NULL) && (ent->content != NULL)) {
 
2397
                ctxt->depth++;
 
2398
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 
2399
                                              0, 0, 0);
 
2400
                ctxt->depth--;
 
2401
                if (rep != NULL) {
 
2402
                    current = rep;
 
2403
                    while (*current != 0) { /* non input consuming loop */
 
2404
                        buffer[nbchars++] = *current++;
 
2405
                        if (nbchars >
 
2406
                            buffer_size - XML_PARSER_BUFFER_SIZE) {
 
2407
                            growBuffer(buffer);
 
2408
                        }
 
2409
                    }
 
2410
                    xmlFree(rep);
 
2411
                    rep = NULL;
 
2412
                }
 
2413
            } else if (ent != NULL) {
 
2414
                int i = xmlStrlen(ent->name);
 
2415
                const xmlChar *cur = ent->name;
 
2416
 
 
2417
                buffer[nbchars++] = '&';
 
2418
                if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
 
2419
                    growBuffer(buffer);
 
2420
                }
 
2421
                for (;i > 0;i--)
 
2422
                    buffer[nbchars++] = *cur++;
 
2423
                buffer[nbchars++] = ';';
 
2424
            }
 
2425
        } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
 
2426
            if (xmlParserDebugEntities)
 
2427
                xmlGenericError(xmlGenericErrorContext,
 
2428
                        "String decoding PE Reference: %.30s\n", str);
 
2429
            ent = xmlParseStringPEReference(ctxt, &str);
 
2430
            if (ent != NULL) {
 
2431
                if (ent->content == NULL) {
 
2432
                    if (xmlLoadEntityContent(ctxt, ent) < 0) {
 
2433
                    }
 
2434
                }
 
2435
                ctxt->depth++;
 
2436
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 
2437
                                              0, 0, 0);
 
2438
                ctxt->depth--;
 
2439
                if (rep != NULL) {
 
2440
                    current = rep;
 
2441
                    while (*current != 0) { /* non input consuming loop */
 
2442
                        buffer[nbchars++] = *current++;
 
2443
                        if (nbchars >
 
2444
                            buffer_size - XML_PARSER_BUFFER_SIZE) {
 
2445
                            growBuffer(buffer);
 
2446
                        }
 
2447
                    }
 
2448
                    xmlFree(rep);
 
2449
                    rep = NULL;
 
2450
                }
 
2451
            }
 
2452
        } else {
 
2453
            COPY_BUF(l,buffer,nbchars,c);
 
2454
            str += l;
 
2455
            if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
 
2456
              growBuffer(buffer);
 
2457
            }
 
2458
        }
 
2459
        if (str < last)
 
2460
            c = CUR_SCHAR(str, l);
 
2461
        else
 
2462
            c = 0;
 
2463
    }
 
2464
    buffer[nbchars++] = 0;
 
2465
    return(buffer);
 
2466
 
 
2467
mem_error:
 
2468
    xmlErrMemory(ctxt, NULL);
 
2469
    if (rep != NULL)
 
2470
        xmlFree(rep);
 
2471
    if (buffer != NULL)
 
2472
        xmlFree(buffer);
 
2473
    return(NULL);
 
2474
}
 
2475
 
 
2476
/**
 
2477
 * xmlStringDecodeEntities:
 
2478
 * @ctxt:  the parser context
 
2479
 * @str:  the input string
 
2480
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
 
2481
 * @end:  an end marker xmlChar, 0 if none
 
2482
 * @end2:  an end marker xmlChar, 0 if none
 
2483
 * @end3:  an end marker xmlChar, 0 if none
 
2484
 * 
 
2485
 * Takes a entity string content and process to do the adequate substitutions.
 
2486
 *
 
2487
 * [67] Reference ::= EntityRef | CharRef
 
2488
 *
 
2489
 * [69] PEReference ::= '%' Name ';'
 
2490
 *
 
2491
 * Returns A newly allocated string with the substitution done. The caller
 
2492
 *      must deallocate it !
 
2493
 */
 
2494
xmlChar *
 
2495
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
 
2496
                        xmlChar end, xmlChar  end2, xmlChar end3) {
 
2497
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
 
2498
    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
 
2499
           end, end2, end3));
 
2500
}
 
2501
 
 
2502
/************************************************************************
 
2503
 *                                                                      *
 
2504
 *              Commodity functions, cleanup needed ?                   *
 
2505
 *                                                                      *
 
2506
 ************************************************************************/
 
2507
 
 
2508
/**
 
2509
 * areBlanks:
 
2510
 * @ctxt:  an XML parser context
 
2511
 * @str:  a xmlChar *
 
2512
 * @len:  the size of @str
 
2513
 * @blank_chars: we know the chars are blanks
 
2514
 *
 
2515
 * Is this a sequence of blank chars that one can ignore ?
 
2516
 *
 
2517
 * Returns 1 if ignorable 0 otherwise.
 
2518
 */
 
2519
 
 
2520
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
 
2521
                     int blank_chars) {
 
2522
    int i, ret;
 
2523
    xmlNodePtr lastChild;
 
2524
 
 
2525
    /*
 
2526
     * Don't spend time trying to differentiate them, the same callback is
 
2527
     * used !
 
2528
     */
 
2529
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
 
2530
        return(0);
 
2531
 
 
2532
    /*
 
2533
     * Check for xml:space value.
 
2534
     */
 
2535
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
 
2536
        (*(ctxt->space) == -2))
 
2537
        return(0);
 
2538
 
 
2539
    /*
 
2540
     * Check that the string is made of blanks
 
2541
     */
 
2542
    if (blank_chars == 0) {
 
2543
        for (i = 0;i < len;i++)
 
2544
            if (!(IS_BLANK_CH(str[i]))) return(0);
 
2545
    }
 
2546
 
 
2547
    /*
 
2548
     * Look if the element is mixed content in the DTD if available
 
2549
     */
 
2550
    if (ctxt->node == NULL) return(0);
 
2551
    if (ctxt->myDoc != NULL) {
 
2552
        ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
 
2553
        if (ret == 0) return(1);
 
2554
        if (ret == 1) return(0);
 
2555
    }
 
2556
 
 
2557
    /*
 
2558
     * Otherwise, heuristic :-\
 
2559
     */
 
2560
    if ((RAW != '<') && (RAW != 0xD)) return(0);
 
2561
    if ((ctxt->node->children == NULL) &&
 
2562
        (RAW == '<') && (NXT(1) == '/')) return(0);
 
2563
 
 
2564
    lastChild = xmlGetLastChild(ctxt->node);
 
2565
    if (lastChild == NULL) {
 
2566
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
 
2567
            (ctxt->node->content != NULL)) return(0);
 
2568
    } else if (xmlNodeIsText(lastChild))
 
2569
        return(0);
 
2570
    else if ((ctxt->node->children != NULL) &&
 
2571
             (xmlNodeIsText(ctxt->node->children)))
 
2572
        return(0);
 
2573
    return(1);
 
2574
}
 
2575
 
 
2576
/************************************************************************
 
2577
 *                                                                      *
 
2578
 *              Extra stuff for namespace support                       *
 
2579
 *      Relates to http://www.w3.org/TR/WD-xml-names                    *
 
2580
 *                                                                      *
 
2581
 ************************************************************************/
 
2582
 
 
2583
/**
 
2584
 * xmlSplitQName:
 
2585
 * @ctxt:  an XML parser context
 
2586
 * @name:  an XML parser context
 
2587
 * @prefix:  a xmlChar **
 
2588
 *
 
2589
 * parse an UTF8 encoded XML qualified name string
 
2590
 *
 
2591
 * [NS 5] QName ::= (Prefix ':')? LocalPart
 
2592
 *
 
2593
 * [NS 6] Prefix ::= NCName
 
2594
 *
 
2595
 * [NS 7] LocalPart ::= NCName
 
2596
 *
 
2597
 * Returns the local part, and prefix is updated
 
2598
 *   to get the Prefix if any.
 
2599
 */
 
2600
 
 
2601
xmlChar *
 
2602
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 
2603
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
2604
    xmlChar *buffer = NULL;
 
2605
    int len = 0;
 
2606
    int max = XML_MAX_NAMELEN;
 
2607
    xmlChar *ret = NULL;
 
2608
    const xmlChar *cur = name;
 
2609
    int c;
 
2610
 
 
2611
    if (prefix == NULL) return(NULL);
 
2612
    *prefix = NULL;
 
2613
 
 
2614
    if (cur == NULL) return(NULL);
 
2615
 
 
2616
#ifndef XML_XML_NAMESPACE
 
2617
    /* xml: prefix is not really a namespace */
 
2618
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
 
2619
        (cur[2] == 'l') && (cur[3] == ':'))
 
2620
        return(xmlStrdup(name));
 
2621
#endif
 
2622
 
 
2623
    /* nasty but well=formed */
 
2624
    if (cur[0] == ':')
 
2625
        return(xmlStrdup(name));
 
2626
 
 
2627
    c = *cur++;
 
2628
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
 
2629
        buf[len++] = c;
 
2630
        c = *cur++;
 
2631
    }
 
2632
    if (len >= max) {
 
2633
        /*
 
2634
         * Okay someone managed to make a huge name, so he's ready to pay
 
2635
         * for the processing speed.
 
2636
         */
 
2637
        max = len * 2;
 
2638
 
 
2639
        buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
2640
        if (buffer == NULL) {
 
2641
            xmlErrMemory(ctxt, NULL);
 
2642
            return(NULL);
 
2643
        }
 
2644
        memcpy(buffer, buf, len);
 
2645
        while ((c != 0) && (c != ':')) { /* tested bigname.xml */
 
2646
            if (len + 10 > max) {
 
2647
                xmlChar *tmp;
 
2648
 
 
2649
                max *= 2;
 
2650
                tmp = (xmlChar *) xmlRealloc(buffer,
 
2651
                                                max * sizeof(xmlChar));
 
2652
                if (tmp == NULL) {
 
2653
                    xmlFree(buffer);
 
2654
                    xmlErrMemory(ctxt, NULL);
 
2655
                    return(NULL);
 
2656
                }
 
2657
                buffer = tmp;
 
2658
            }
 
2659
            buffer[len++] = c;
 
2660
            c = *cur++;
 
2661
        }
 
2662
        buffer[len] = 0;
 
2663
    }
 
2664
 
 
2665
    if ((c == ':') && (*cur == 0)) {
 
2666
        if (buffer != NULL)
 
2667
            xmlFree(buffer);
 
2668
        *prefix = NULL;
 
2669
        return(xmlStrdup(name));
 
2670
    }
 
2671
 
 
2672
    if (buffer == NULL)
 
2673
        ret = xmlStrndup(buf, len);
 
2674
    else {
 
2675
        ret = buffer;
 
2676
        buffer = NULL;
 
2677
        max = XML_MAX_NAMELEN;
 
2678
    }
 
2679
 
 
2680
 
 
2681
    if (c == ':') {
 
2682
        c = *cur;
 
2683
        *prefix = ret;
 
2684
        if (c == 0) {
 
2685
            return(xmlStrndup(BAD_CAST "", 0));
 
2686
        }
 
2687
        len = 0;
 
2688
 
 
2689
        /*
 
2690
         * Check that the first character is proper to start
 
2691
         * a new name
 
2692
         */
 
2693
        if (!(((c >= 0x61) && (c <= 0x7A)) ||
 
2694
              ((c >= 0x41) && (c <= 0x5A)) ||
 
2695
              (c == '_') || (c == ':'))) {
 
2696
            int l;
 
2697
            int first = CUR_SCHAR(cur, l);
 
2698
 
 
2699
            if (!IS_LETTER(first) && (first != '_')) {
 
2700
                xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
 
2701
                            "Name %s is not XML Namespace compliant\n",
 
2702
                                  name);
 
2703
            }
 
2704
        }
 
2705
        cur++;
 
2706
 
 
2707
        while ((c != 0) && (len < max)) { /* tested bigname2.xml */
 
2708
            buf[len++] = c;
 
2709
            c = *cur++;
 
2710
        }
 
2711
        if (len >= max) {
 
2712
            /*
 
2713
             * Okay someone managed to make a huge name, so he's ready to pay
 
2714
             * for the processing speed.
 
2715
             */
 
2716
            max = len * 2;
 
2717
 
 
2718
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
2719
            if (buffer == NULL) {
 
2720
                xmlErrMemory(ctxt, NULL);
 
2721
                return(NULL);
 
2722
            }
 
2723
            memcpy(buffer, buf, len);
 
2724
            while (c != 0) { /* tested bigname2.xml */
 
2725
                if (len + 10 > max) {
 
2726
                    xmlChar *tmp;
 
2727
 
 
2728
                    max *= 2;
 
2729
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
2730
                                                    max * sizeof(xmlChar));
 
2731
                    if (tmp == NULL) {
 
2732
                        xmlErrMemory(ctxt, NULL);
 
2733
                        xmlFree(buffer);
 
2734
                        return(NULL);
 
2735
                    }
 
2736
                    buffer = tmp;
 
2737
                }
 
2738
                buffer[len++] = c;
 
2739
                c = *cur++;
 
2740
            }
 
2741
            buffer[len] = 0;
 
2742
        }
 
2743
 
 
2744
        if (buffer == NULL)
 
2745
            ret = xmlStrndup(buf, len);
 
2746
        else {
 
2747
            ret = buffer;
 
2748
        }
 
2749
    }
 
2750
 
 
2751
    return(ret);
 
2752
}
 
2753
 
 
2754
/************************************************************************
 
2755
 *                                                                      *
 
2756
 *                      The parser itself                               *
 
2757
 *      Relates to http://www.w3.org/TR/REC-xml                         *
 
2758
 *                                                                      *
 
2759
 ************************************************************************/
 
2760
 
 
2761
static const xmlChar * xmlParseNameComplex(xmlParserCtxtPtr ctxt);
 
2762
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
 
2763
                                          int *len, int *alloc, int normalize);
 
2764
 
 
2765
/**
 
2766
 * xmlParseName:
 
2767
 * @ctxt:  an XML parser context
 
2768
 *
 
2769
 * parse an XML name.
 
2770
 *
 
2771
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
 
2772
 *                  CombiningChar | Extender
 
2773
 *
 
2774
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
 
2775
 *
 
2776
 * [6] Names ::= Name (#x20 Name)*
 
2777
 *
 
2778
 * Returns the Name parsed or NULL
 
2779
 */
 
2780
 
 
2781
const xmlChar *
 
2782
xmlParseName(xmlParserCtxtPtr ctxt) {
 
2783
    const xmlChar *in;
 
2784
    const xmlChar *ret;
 
2785
    int count = 0;
 
2786
 
 
2787
    GROW;
 
2788
 
 
2789
    /*
 
2790
     * Accelerator for simple ASCII names
 
2791
     */
 
2792
    in = ctxt->input->cur;
 
2793
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
 
2794
        ((*in >= 0x41) && (*in <= 0x5A)) ||
 
2795
        (*in == '_') || (*in == ':')) {
 
2796
        in++;
 
2797
        while (((*in >= 0x61) && (*in <= 0x7A)) ||
 
2798
               ((*in >= 0x41) && (*in <= 0x5A)) ||
 
2799
               ((*in >= 0x30) && (*in <= 0x39)) ||
 
2800
               (*in == '_') || (*in == '-') ||
 
2801
               (*in == ':') || (*in == '.'))
 
2802
            in++;
 
2803
        if ((*in > 0) && (*in < 0x80)) {
 
2804
            count = in - ctxt->input->cur;
 
2805
            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 
2806
            ctxt->input->cur = in;
 
2807
            ctxt->nbChars += count;
 
2808
            ctxt->input->col += count;
 
2809
            if (ret == NULL)
 
2810
                xmlErrMemory(ctxt, NULL);
 
2811
            return(ret);
 
2812
        }
 
2813
    }
 
2814
    return(xmlParseNameComplex(ctxt));
 
2815
}
 
2816
 
 
2817
/**
 
2818
 * xmlParseNameAndCompare:
 
2819
 * @ctxt:  an XML parser context
 
2820
 *
 
2821
 * parse an XML name and compares for match
 
2822
 * (specialized for endtag parsing)
 
2823
 *
 
2824
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
 
2825
 * and the name for mismatch
 
2826
 */
 
2827
 
 
2828
static const xmlChar *
 
2829
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
 
2830
    register const xmlChar *cmp = other;
 
2831
    register const xmlChar *in;
 
2832
    const xmlChar *ret;
 
2833
 
 
2834
    GROW;
 
2835
    
 
2836
    in = ctxt->input->cur;
 
2837
    while (*in != 0 && *in == *cmp) {
 
2838
        ++in;
 
2839
        ++cmp;
 
2840
        ctxt->input->col++;
 
2841
    }
 
2842
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 
2843
        /* success */
 
2844
        ctxt->input->cur = in;
 
2845
        return (const xmlChar*) 1;
 
2846
    }
 
2847
    /* failure (or end of input buffer), check with full function */
 
2848
    ret = xmlParseName (ctxt);
 
2849
    /* strings coming from the dictionnary direct compare possible */
 
2850
    if (ret == other) {
 
2851
        return (const xmlChar*) 1;
 
2852
    }
 
2853
    return ret;
 
2854
}
 
2855
 
 
2856
static const xmlChar *
 
2857
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
 
2858
    int len = 0, l;
 
2859
    int c;
 
2860
    int count = 0;
 
2861
 
 
2862
    /*
 
2863
     * Handler for more complex cases
 
2864
     */
 
2865
    GROW;
 
2866
    c = CUR_CHAR(l);
 
2867
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
2868
        (!IS_LETTER(c) && (c != '_') &&
 
2869
         (c != ':'))) {
 
2870
        return(NULL);
 
2871
    }
 
2872
 
 
2873
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 
2874
           ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
2875
            (c == '.') || (c == '-') ||
 
2876
            (c == '_') || (c == ':') || 
 
2877
            (IS_COMBINING(c)) ||
 
2878
            (IS_EXTENDER(c)))) {
 
2879
        if (count++ > 100) {
 
2880
            count = 0;
 
2881
            GROW;
 
2882
        }
 
2883
        len += l;
 
2884
        NEXTL(l);
 
2885
        c = CUR_CHAR(l);
 
2886
    }
 
2887
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
 
2888
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
 
2889
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 
2890
}
 
2891
 
 
2892
/**
 
2893
 * xmlParseStringName:
 
2894
 * @ctxt:  an XML parser context
 
2895
 * @str:  a pointer to the string pointer (IN/OUT)
 
2896
 *
 
2897
 * parse an XML name.
 
2898
 *
 
2899
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
 
2900
 *                  CombiningChar | Extender
 
2901
 *
 
2902
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
 
2903
 *
 
2904
 * [6] Names ::= Name (#x20 Name)*
 
2905
 *
 
2906
 * Returns the Name parsed or NULL. The @str pointer 
 
2907
 * is updated to the current location in the string.
 
2908
 */
 
2909
 
 
2910
static xmlChar *
 
2911
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
 
2912
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
2913
    const xmlChar *cur = *str;
 
2914
    int len = 0, l;
 
2915
    int c;
 
2916
 
 
2917
    c = CUR_SCHAR(cur, l);
 
2918
    if (!IS_LETTER(c) && (c != '_') &&
 
2919
        (c != ':')) {
 
2920
        return(NULL);
 
2921
    }
 
2922
 
 
2923
    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigentname.xml */
 
2924
           (c == '.') || (c == '-') ||
 
2925
           (c == '_') || (c == ':') || 
 
2926
           (IS_COMBINING(c)) ||
 
2927
           (IS_EXTENDER(c))) {
 
2928
        COPY_BUF(l,buf,len,c);
 
2929
        cur += l;
 
2930
        c = CUR_SCHAR(cur, l);
 
2931
        if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
 
2932
            /*
 
2933
             * Okay someone managed to make a huge name, so he's ready to pay
 
2934
             * for the processing speed.
 
2935
             */
 
2936
            xmlChar *buffer;
 
2937
            int max = len * 2;
 
2938
            
 
2939
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
2940
            if (buffer == NULL) {
 
2941
                xmlErrMemory(ctxt, NULL);
 
2942
                return(NULL);
 
2943
            }
 
2944
            memcpy(buffer, buf, len);
 
2945
            while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
2946
                     /* test bigentname.xml */
 
2947
                   (c == '.') || (c == '-') ||
 
2948
                   (c == '_') || (c == ':') || 
 
2949
                   (IS_COMBINING(c)) ||
 
2950
                   (IS_EXTENDER(c))) {
 
2951
                if (len + 10 > max) {
 
2952
                    xmlChar *tmp;
 
2953
                    max *= 2;
 
2954
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
2955
                                                    max * sizeof(xmlChar));
 
2956
                    if (tmp == NULL) {
 
2957
                        xmlErrMemory(ctxt, NULL);
 
2958
                        xmlFree(buffer);
 
2959
                        return(NULL);
 
2960
                    }
 
2961
                    buffer = tmp;
 
2962
                }
 
2963
                COPY_BUF(l,buffer,len,c);
 
2964
                cur += l;
 
2965
                c = CUR_SCHAR(cur, l);
 
2966
            }
 
2967
            buffer[len] = 0;
 
2968
            *str = cur;
 
2969
            return(buffer);
 
2970
        }
 
2971
    }
 
2972
    *str = cur;
 
2973
    return(xmlStrndup(buf, len));
 
2974
}
 
2975
 
 
2976
/**
 
2977
 * xmlParseNmtoken:
 
2978
 * @ctxt:  an XML parser context
 
2979
 * 
 
2980
 * parse an XML Nmtoken.
 
2981
 *
 
2982
 * [7] Nmtoken ::= (NameChar)+
 
2983
 *
 
2984
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
 
2985
 *
 
2986
 * Returns the Nmtoken parsed or NULL
 
2987
 */
 
2988
 
 
2989
xmlChar *
 
2990
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
 
2991
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
2992
    int len = 0, l;
 
2993
    int c;
 
2994
    int count = 0;
 
2995
 
 
2996
    GROW;
 
2997
    c = CUR_CHAR(l);
 
2998
 
 
2999
    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */
 
3000
           (c == '.') || (c == '-') ||
 
3001
           (c == '_') || (c == ':') || 
 
3002
           (IS_COMBINING(c)) ||
 
3003
           (IS_EXTENDER(c))) {
 
3004
        if (count++ > 100) {
 
3005
            count = 0;
 
3006
            GROW;
 
3007
        }
 
3008
        COPY_BUF(l,buf,len,c);
 
3009
        NEXTL(l);
 
3010
        c = CUR_CHAR(l);
 
3011
        if (len >= XML_MAX_NAMELEN) {
 
3012
            /*
 
3013
             * Okay someone managed to make a huge token, so he's ready to pay
 
3014
             * for the processing speed.
 
3015
             */
 
3016
            xmlChar *buffer;
 
3017
            int max = len * 2;
 
3018
            
 
3019
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3020
            if (buffer == NULL) {
 
3021
                xmlErrMemory(ctxt, NULL);
 
3022
                return(NULL);
 
3023
            }
 
3024
            memcpy(buffer, buf, len);
 
3025
            while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */
 
3026
                   (c == '.') || (c == '-') ||
 
3027
                   (c == '_') || (c == ':') || 
 
3028
                   (IS_COMBINING(c)) ||
 
3029
                   (IS_EXTENDER(c))) {
 
3030
                if (count++ > 100) {
 
3031
                    count = 0;
 
3032
                    GROW;
 
3033
                }
 
3034
                if (len + 10 > max) {
 
3035
                    xmlChar *tmp;
 
3036
 
 
3037
                    max *= 2;
 
3038
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3039
                                                    max * sizeof(xmlChar));
 
3040
                    if (tmp == NULL) {
 
3041
                        xmlErrMemory(ctxt, NULL);
 
3042
                        xmlFree(buffer);
 
3043
                        return(NULL);
 
3044
                    }
 
3045
                    buffer = tmp;
 
3046
                }
 
3047
                COPY_BUF(l,buffer,len,c);
 
3048
                NEXTL(l);
 
3049
                c = CUR_CHAR(l);
 
3050
            }
 
3051
            buffer[len] = 0;
 
3052
            return(buffer);
 
3053
        }
 
3054
    }
 
3055
    if (len == 0)
 
3056
        return(NULL);
 
3057
    return(xmlStrndup(buf, len));
 
3058
}
 
3059
 
 
3060
/**
 
3061
 * xmlParseEntityValue:
 
3062
 * @ctxt:  an XML parser context
 
3063
 * @orig:  if non-NULL store a copy of the original entity value
 
3064
 *
 
3065
 * parse a value for ENTITY declarations
 
3066
 *
 
3067
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
 
3068
 *                     "'" ([^%&'] | PEReference | Reference)* "'"
 
3069
 *
 
3070
 * Returns the EntityValue parsed with reference substituted or NULL
 
3071
 */
 
3072
 
 
3073
xmlChar *
 
3074
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
 
3075
    xmlChar *buf = NULL;
 
3076
    int len = 0;
 
3077
    int size = XML_PARSER_BUFFER_SIZE;
 
3078
    int c, l;
 
3079
    xmlChar stop;
 
3080
    xmlChar *ret = NULL;
 
3081
    const xmlChar *cur = NULL;
 
3082
    xmlParserInputPtr input;
 
3083
 
 
3084
    if (RAW == '"') stop = '"';
 
3085
    else if (RAW == '\'') stop = '\'';
 
3086
    else {
 
3087
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
 
3088
        return(NULL);
 
3089
    }
 
3090
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
3091
    if (buf == NULL) {
 
3092
        xmlErrMemory(ctxt, NULL);
 
3093
        return(NULL);
 
3094
    }
 
3095
 
 
3096
    /*
 
3097
     * The content of the entity definition is copied in a buffer.
 
3098
     */
 
3099
 
 
3100
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
 
3101
    input = ctxt->input;
 
3102
    GROW;
 
3103
    NEXT;
 
3104
    c = CUR_CHAR(l);
 
3105
    /*
 
3106
     * NOTE: 4.4.5 Included in Literal
 
3107
     * When a parameter entity reference appears in a literal entity
 
3108
     * value, ... a single or double quote character in the replacement
 
3109
     * text is always treated as a normal data character and will not
 
3110
     * terminate the literal. 
 
3111
     * In practice it means we stop the loop only when back at parsing
 
3112
     * the initial entity and the quote is found
 
3113
     */
 
3114
    while ((IS_CHAR(c)) && ((c != stop) || /* checked */
 
3115
           (ctxt->input != input))) {
 
3116
        if (len + 5 >= size) {
 
3117
            xmlChar *tmp;
 
3118
 
 
3119
            size *= 2;
 
3120
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
3121
            if (tmp == NULL) {
 
3122
                xmlErrMemory(ctxt, NULL);
 
3123
                xmlFree(buf);
 
3124
                return(NULL);
 
3125
            }
 
3126
            buf = tmp;
 
3127
        }
 
3128
        COPY_BUF(l,buf,len,c);
 
3129
        NEXTL(l);
 
3130
        /*
 
3131
         * Pop-up of finished entities.
 
3132
         */
 
3133
        while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
 
3134
            xmlPopInput(ctxt);
 
3135
 
 
3136
        GROW;
 
3137
        c = CUR_CHAR(l);
 
3138
        if (c == 0) {
 
3139
            GROW;
 
3140
            c = CUR_CHAR(l);
 
3141
        }
 
3142
    }
 
3143
    buf[len] = 0;
 
3144
 
 
3145
    /*
 
3146
     * Raise problem w.r.t. '&' and '%' being used in non-entities
 
3147
     * reference constructs. Note Charref will be handled in
 
3148
     * xmlStringDecodeEntities()
 
3149
     */
 
3150
    cur = buf;
 
3151
    while (*cur != 0) { /* non input consuming */
 
3152
        if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
 
3153
            xmlChar *name;
 
3154
            xmlChar tmp = *cur;
 
3155
 
 
3156
            cur++;
 
3157
            name = xmlParseStringName(ctxt, &cur);
 
3158
            if ((name == NULL) || (*cur != ';')) {
 
3159
                xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
 
3160
            "EntityValue: '%c' forbidden except for entities references\n",
 
3161
                                  tmp);
 
3162
            }
 
3163
            if ((tmp == '%') && (ctxt->inSubset == 1) &&
 
3164
                (ctxt->inputNr == 1)) {
 
3165
                xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
 
3166
            }
 
3167
            if (name != NULL)
 
3168
                xmlFree(name);
 
3169
            if (*cur == 0)
 
3170
                break;
 
3171
        }
 
3172
        cur++;
 
3173
    }
 
3174
 
 
3175
    /*
 
3176
     * Then PEReference entities are substituted.
 
3177
     */
 
3178
    if (c != stop) {
 
3179
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
 
3180
        xmlFree(buf);
 
3181
    } else {
 
3182
        NEXT;
 
3183
        /*
 
3184
         * NOTE: 4.4.7 Bypassed
 
3185
         * When a general entity reference appears in the EntityValue in
 
3186
         * an entity declaration, it is bypassed and left as is.
 
3187
         * so XML_SUBSTITUTE_REF is not set here.
 
3188
         */
 
3189
        ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
 
3190
                                      0, 0, 0);
 
3191
        if (orig != NULL) 
 
3192
            *orig = buf;
 
3193
        else
 
3194
            xmlFree(buf);
 
3195
    }
 
3196
    
 
3197
    return(ret);
 
3198
}
 
3199
 
 
3200
/**
 
3201
 * xmlParseAttValueComplex:
 
3202
 * @ctxt:  an XML parser context
 
3203
 * @len:   the resulting attribute len
 
3204
 * @normalize:  wether to apply the inner normalization
 
3205
 *
 
3206
 * parse a value for an attribute, this is the fallback function
 
3207
 * of xmlParseAttValue() when the attribute parsing requires handling
 
3208
 * of non-ASCII characters, or normalization compaction.
 
3209
 *
 
3210
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
 
3211
 */
 
3212
static xmlChar *
 
3213
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
 
3214
    xmlChar limit = 0;
 
3215
    xmlChar *buf = NULL;
 
3216
    xmlChar *rep = NULL;
 
3217
    int len = 0;
 
3218
    int buf_size = 0;
 
3219
    int c, l, in_space = 0;
 
3220
    xmlChar *current = NULL;
 
3221
    xmlEntityPtr ent;
 
3222
 
 
3223
    if (NXT(0) == '"') {
 
3224
        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
3225
        limit = '"';
 
3226
        NEXT;
 
3227
    } else if (NXT(0) == '\'') {
 
3228
        limit = '\'';
 
3229
        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
3230
        NEXT;
 
3231
    } else {
 
3232
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 
3233
        return(NULL);
 
3234
    }
 
3235
 
 
3236
    /*
 
3237
     * allocate a translation buffer.
 
3238
     */
 
3239
    buf_size = XML_PARSER_BUFFER_SIZE;
 
3240
    buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
 
3241
    if (buf == NULL) goto mem_error;
 
3242
 
 
3243
    /*
 
3244
     * OK loop until we reach one of the ending char or a size limit.
 
3245
     */
 
3246
    c = CUR_CHAR(l);
 
3247
    while ((NXT(0) != limit) && /* checked */
 
3248
           (IS_CHAR(c)) && (c != '<')) {
 
3249
        if (c == 0) break;
 
3250
        if (c == '&') {
 
3251
            in_space = 0;
 
3252
            if (NXT(1) == '#') {
 
3253
                int val = xmlParseCharRef(ctxt);
 
3254
 
 
3255
                if (val == '&') {
 
3256
                    if (ctxt->replaceEntities) {
 
3257
                        if (len > buf_size - 10) {
 
3258
                            growBuffer(buf);
 
3259
                        }
 
3260
                        buf[len++] = '&';
 
3261
                    } else {
 
3262
                        /*
 
3263
                         * The reparsing will be done in xmlStringGetNodeList()
 
3264
                         * called by the attribute() function in SAX.c
 
3265
                         */
 
3266
                        if (len > buf_size - 10) {
 
3267
                            growBuffer(buf);
 
3268
                        }
 
3269
                        buf[len++] = '&';
 
3270
                        buf[len++] = '#';
 
3271
                        buf[len++] = '3';
 
3272
                        buf[len++] = '8';
 
3273
                        buf[len++] = ';';
 
3274
                    }
 
3275
                } else if (val != 0) {
 
3276
                    if (len > buf_size - 10) {
 
3277
                        growBuffer(buf);
 
3278
                    }
 
3279
                    len += xmlCopyChar(0, &buf[len], val);
 
3280
                }
 
3281
            } else {
 
3282
                ent = xmlParseEntityRef(ctxt);
 
3283
                if ((ent != NULL) &&
 
3284
                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
3285
                    if (len > buf_size - 10) {
 
3286
                        growBuffer(buf);
 
3287
                    }
 
3288
                    if ((ctxt->replaceEntities == 0) &&
 
3289
                        (ent->content[0] == '&')) {
 
3290
                        buf[len++] = '&';
 
3291
                        buf[len++] = '#';
 
3292
                        buf[len++] = '3';
 
3293
                        buf[len++] = '8';
 
3294
                        buf[len++] = ';';
 
3295
                    } else {
 
3296
                        buf[len++] = ent->content[0];
 
3297
                    }
 
3298
                } else if ((ent != NULL) && 
 
3299
                           (ctxt->replaceEntities != 0)) {
 
3300
                    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
 
3301
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
3302
                                                      XML_SUBSTITUTE_REF,
 
3303
                                                      0, 0, 0);
 
3304
                        if (rep != NULL) {
 
3305
                            current = rep;
 
3306
                            while (*current != 0) { /* non input consuming */
 
3307
                                buf[len++] = *current++;
 
3308
                                if (len > buf_size - 10) {
 
3309
                                    growBuffer(buf);
 
3310
                                }
 
3311
                            }
 
3312
                            xmlFree(rep);
 
3313
                            rep = NULL;
 
3314
                        }
 
3315
                    } else {
 
3316
                        if (len > buf_size - 10) {
 
3317
                            growBuffer(buf);
 
3318
                        }
 
3319
                        if (ent->content != NULL)
 
3320
                            buf[len++] = ent->content[0];
 
3321
                    }
 
3322
                } else if (ent != NULL) {
 
3323
                    int i = xmlStrlen(ent->name);
 
3324
                    const xmlChar *cur = ent->name;
 
3325
 
 
3326
                    /*
 
3327
                     * This may look absurd but is needed to detect
 
3328
                     * entities problems
 
3329
                     */
 
3330
                    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
 
3331
                        (ent->content != NULL)) {
 
3332
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
3333
                                                  XML_SUBSTITUTE_REF, 0, 0, 0);
 
3334
                        if (rep != NULL) {
 
3335
                            xmlFree(rep);
 
3336
                            rep = NULL;
 
3337
                        }
 
3338
                    }
 
3339
 
 
3340
                    /*
 
3341
                     * Just output the reference
 
3342
                     */
 
3343
                    buf[len++] = '&';
 
3344
                    if (len > buf_size - i - 10) {
 
3345
                        growBuffer(buf);
 
3346
                    }
 
3347
                    for (;i > 0;i--)
 
3348
                        buf[len++] = *cur++;
 
3349
                    buf[len++] = ';';
 
3350
                }
 
3351
            }
 
3352
        } else {
 
3353
            if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
 
3354
                if ((len != 0) || (!normalize)) {
 
3355
                    if ((!normalize) || (!in_space)) {
 
3356
                        COPY_BUF(l,buf,len,0x20);
 
3357
                        if (len > buf_size - 10) {
 
3358
                            growBuffer(buf);
 
3359
                        }
 
3360
                    }
 
3361
                    in_space = 1;
 
3362
                }
 
3363
            } else {
 
3364
                in_space = 0;
 
3365
                COPY_BUF(l,buf,len,c);
 
3366
                if (len > buf_size - 10) {
 
3367
                    growBuffer(buf);
 
3368
                }
 
3369
            }
 
3370
            NEXTL(l);
 
3371
        }
 
3372
        GROW;
 
3373
        c = CUR_CHAR(l);
 
3374
    }
 
3375
    if ((in_space) && (normalize)) {
 
3376
        while (buf[len - 1] == 0x20) len--;
 
3377
    }
 
3378
    buf[len] = 0;
 
3379
    if (RAW == '<') {
 
3380
        xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
 
3381
    } else if (RAW != limit) {
 
3382
        if ((c != 0) && (!IS_CHAR(c))) {
 
3383
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
 
3384
                           "invalid character in attribute value\n");
 
3385
        } else {
 
3386
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
3387
                           "AttValue: ' expected\n");
 
3388
        }
 
3389
    } else
 
3390
        NEXT;
 
3391
    if (attlen != NULL) *attlen = len;
 
3392
    return(buf);
 
3393
 
 
3394
mem_error:
 
3395
    xmlErrMemory(ctxt, NULL);
 
3396
    if (buf != NULL)
 
3397
        xmlFree(buf);
 
3398
    if (rep != NULL)
 
3399
        xmlFree(rep);
 
3400
    return(NULL);
 
3401
}
 
3402
 
 
3403
/**
 
3404
 * xmlParseAttValue:
 
3405
 * @ctxt:  an XML parser context
 
3406
 *
 
3407
 * parse a value for an attribute
 
3408
 * Note: the parser won't do substitution of entities here, this
 
3409
 * will be handled later in xmlStringGetNodeList
 
3410
 *
 
3411
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
 
3412
 *                   "'" ([^<&'] | Reference)* "'"
 
3413
 *
 
3414
 * 3.3.3 Attribute-Value Normalization:
 
3415
 * Before the value of an attribute is passed to the application or
 
3416
 * checked for validity, the XML processor must normalize it as follows: 
 
3417
 * - a character reference is processed by appending the referenced
 
3418
 *   character to the attribute value
 
3419
 * - an entity reference is processed by recursively processing the
 
3420
 *   replacement text of the entity 
 
3421
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
 
3422
 *   appending #x20 to the normalized value, except that only a single
 
3423
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
 
3424
 *   parsed entity or the literal entity value of an internal parsed entity 
 
3425
 * - other characters are processed by appending them to the normalized value 
 
3426
 * If the declared value is not CDATA, then the XML processor must further
 
3427
 * process the normalized attribute value by discarding any leading and
 
3428
 * trailing space (#x20) characters, and by replacing sequences of space
 
3429
 * (#x20) characters by a single space (#x20) character.  
 
3430
 * All attributes for which no declaration has been read should be treated
 
3431
 * by a non-validating parser as if declared CDATA.
 
3432
 *
 
3433
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
 
3434
 */
 
3435
 
 
3436
 
 
3437
xmlChar *
 
3438
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
 
3439
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
 
3440
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
 
3441
}
 
3442
 
 
3443
/**
 
3444
 * xmlParseSystemLiteral:
 
3445
 * @ctxt:  an XML parser context
 
3446
 * 
 
3447
 * parse an XML Literal
 
3448
 *
 
3449
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
 
3450
 *
 
3451
 * Returns the SystemLiteral parsed or NULL
 
3452
 */
 
3453
 
 
3454
xmlChar *
 
3455
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
 
3456
    xmlChar *buf = NULL;
 
3457
    int len = 0;
 
3458
    int size = XML_PARSER_BUFFER_SIZE;
 
3459
    int cur, l;
 
3460
    xmlChar stop;
 
3461
    int state = ctxt->instate;
 
3462
    int count = 0;
 
3463
 
 
3464
    SHRINK;
 
3465
    if (RAW == '"') {
 
3466
        NEXT;
 
3467
        stop = '"';
 
3468
    } else if (RAW == '\'') {
 
3469
        NEXT;
 
3470
        stop = '\'';
 
3471
    } else {
 
3472
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 
3473
        return(NULL);
 
3474
    }
 
3475
    
 
3476
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
3477
    if (buf == NULL) {
 
3478
        xmlErrMemory(ctxt, NULL);
 
3479
        return(NULL);
 
3480
    }
 
3481
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
 
3482
    cur = CUR_CHAR(l);
 
3483
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
 
3484
        if (len + 5 >= size) {
 
3485
            xmlChar *tmp;
 
3486
 
 
3487
            size *= 2;
 
3488
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
3489
            if (tmp == NULL) {
 
3490
                xmlFree(buf);
 
3491
                xmlErrMemory(ctxt, NULL);
 
3492
                ctxt->instate = (xmlParserInputState) state;
 
3493
                return(NULL);
 
3494
            }
 
3495
            buf = tmp;
 
3496
        }
 
3497
        count++;
 
3498
        if (count > 50) {
 
3499
            GROW;
 
3500
            count = 0;
 
3501
        }
 
3502
        COPY_BUF(l,buf,len,cur);
 
3503
        NEXTL(l);
 
3504
        cur = CUR_CHAR(l);
 
3505
        if (cur == 0) {
 
3506
            GROW;
 
3507
            SHRINK;
 
3508
            cur = CUR_CHAR(l);
 
3509
        }
 
3510
    }
 
3511
    buf[len] = 0;
 
3512
    ctxt->instate = (xmlParserInputState) state;
 
3513
    if (!IS_CHAR(cur)) {
 
3514
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 
3515
    } else {
 
3516
        NEXT;
 
3517
    }
 
3518
    return(buf);
 
3519
}
 
3520
 
 
3521
/**
 
3522
 * xmlParsePubidLiteral:
 
3523
 * @ctxt:  an XML parser context
 
3524
 *
 
3525
 * parse an XML public literal
 
3526
 *
 
3527
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
 
3528
 *
 
3529
 * Returns the PubidLiteral parsed or NULL.
 
3530
 */
 
3531
 
 
3532
xmlChar *
 
3533
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
 
3534
    xmlChar *buf = NULL;
 
3535
    int len = 0;
 
3536
    int size = XML_PARSER_BUFFER_SIZE;
 
3537
    xmlChar cur;
 
3538
    xmlChar stop;
 
3539
    int count = 0;
 
3540
    xmlParserInputState oldstate = ctxt->instate;
 
3541
 
 
3542
    SHRINK;
 
3543
    if (RAW == '"') {
 
3544
        NEXT;
 
3545
        stop = '"';
 
3546
    } else if (RAW == '\'') {
 
3547
        NEXT;
 
3548
        stop = '\'';
 
3549
    } else {
 
3550
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 
3551
        return(NULL);
 
3552
    }
 
3553
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
3554
    if (buf == NULL) {
 
3555
        xmlErrMemory(ctxt, NULL);
 
3556
        return(NULL);
 
3557
    }
 
3558
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
 
3559
    cur = CUR;
 
3560
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
 
3561
        if (len + 1 >= size) {
 
3562
            xmlChar *tmp;
 
3563
 
 
3564
            size *= 2;
 
3565
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
3566
            if (tmp == NULL) {
 
3567
                xmlErrMemory(ctxt, NULL);
 
3568
                xmlFree(buf);
 
3569
                return(NULL);
 
3570
            }
 
3571
            buf = tmp;
 
3572
        }
 
3573
        buf[len++] = cur;
 
3574
        count++;
 
3575
        if (count > 50) {
 
3576
            GROW;
 
3577
            count = 0;
 
3578
        }
 
3579
        NEXT;
 
3580
        cur = CUR;
 
3581
        if (cur == 0) {
 
3582
            GROW;
 
3583
            SHRINK;
 
3584
            cur = CUR;
 
3585
        }
 
3586
    }
 
3587
    buf[len] = 0;
 
3588
    if (cur != stop) {
 
3589
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 
3590
    } else {
 
3591
        NEXT;
 
3592
    }
 
3593
    ctxt->instate = oldstate;
 
3594
    return(buf);
 
3595
}
 
3596
 
 
3597
void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
 
3598
 
 
3599
/*
 
3600
 * used for the test in the inner loop of the char data testing
 
3601
 */
 
3602
static const unsigned char test_char_data[256] = {
 
3603
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3604
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
 
3605
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3606
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3607
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
 
3608
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
 
3609
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 
3610
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
 
3611
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
 
3612
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
 
3613
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
 
3614
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
 
3615
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
 
3616
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
 
3617
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
 
3618
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
 
3619
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
 
3620
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3621
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3622
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3623
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3624
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3625
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3626
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3627
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3628
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3629
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3630
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3631
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3632
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3633
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
3634
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 
3635
};
 
3636
 
 
3637
/**
 
3638
 * xmlParseCharData:
 
3639
 * @ctxt:  an XML parser context
 
3640
 * @cdata:  int indicating whether we are within a CDATA section
 
3641
 *
 
3642
 * parse a CharData section.
 
3643
 * if we are within a CDATA section ']]>' marks an end of section.
 
3644
 *
 
3645
 * The right angle bracket (>) may be represented using the string "&gt;",
 
3646
 * and must, for compatibility, be escaped using "&gt;" or a character
 
3647
 * reference when it appears in the string "]]>" in content, when that
 
3648
 * string is not marking the end of a CDATA section. 
 
3649
 *
 
3650
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
 
3651
 */
 
3652
 
 
3653
void
 
3654
xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
 
3655
    const xmlChar *in;
 
3656
    int nbchar = 0;
 
3657
    int line = ctxt->input->line;
 
3658
    int col = ctxt->input->col;
 
3659
    int ccol;
 
3660
 
 
3661
    SHRINK;
 
3662
    GROW;
 
3663
    /*
 
3664
     * Accelerated common case where input don't need to be
 
3665
     * modified before passing it to the handler.
 
3666
     */
 
3667
    if (!cdata) {
 
3668
        in = ctxt->input->cur;
 
3669
        do {
 
3670
get_more_space:
 
3671
            while (*in == 0x20) { in++; ctxt->input->col++; }
 
3672
            if (*in == 0xA) {
 
3673
                do {
 
3674
                    ctxt->input->line++; ctxt->input->col = 1;
 
3675
                    in++;
 
3676
                } while (*in == 0xA);
 
3677
                goto get_more_space;
 
3678
            }
 
3679
            if (*in == '<') {
 
3680
                nbchar = in - ctxt->input->cur;
 
3681
                if (nbchar > 0) {
 
3682
                    const xmlChar *tmp = ctxt->input->cur;
 
3683
                    ctxt->input->cur = in;
 
3684
 
 
3685
                    if ((ctxt->sax != NULL) &&
 
3686
                        (ctxt->sax->ignorableWhitespace !=
 
3687
                         ctxt->sax->characters)) {
 
3688
                        if (areBlanks(ctxt, tmp, nbchar, 1)) {
 
3689
                            if (ctxt->sax->ignorableWhitespace != NULL)
 
3690
                                ctxt->sax->ignorableWhitespace(ctxt->userData,
 
3691
                                                       tmp, nbchar);
 
3692
                        } else {
 
3693
                            if (ctxt->sax->characters != NULL)
 
3694
                                ctxt->sax->characters(ctxt->userData,
 
3695
                                                      tmp, nbchar);
 
3696
                            if (*ctxt->space == -1)
 
3697
                                *ctxt->space = -2;
 
3698
                        }
 
3699
                    } else if ((ctxt->sax != NULL) &&
 
3700
                               (ctxt->sax->characters != NULL)) {
 
3701
                        ctxt->sax->characters(ctxt->userData,
 
3702
                                              tmp, nbchar);
 
3703
                    }
 
3704
                }
 
3705
                return;
 
3706
            }
 
3707
 
 
3708
get_more:
 
3709
            ccol = ctxt->input->col;
 
3710
            while (test_char_data[*in]) {
 
3711
                in++;
 
3712
                ccol++;
 
3713
            }
 
3714
            ctxt->input->col = ccol;
 
3715
            if (*in == 0xA) {
 
3716
                do {
 
3717
                    ctxt->input->line++; ctxt->input->col = 1;
 
3718
                    in++;
 
3719
                } while (*in == 0xA);
 
3720
                goto get_more;
 
3721
            }
 
3722
            if (*in == ']') {
 
3723
                if ((in[1] == ']') && (in[2] == '>')) {
 
3724
                    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 
3725
                    ctxt->input->cur = in;
 
3726
                    return;
 
3727
                }
 
3728
                in++;
 
3729
                ctxt->input->col++;
 
3730
                goto get_more;
 
3731
            }
 
3732
            nbchar = in - ctxt->input->cur;
 
3733
            if (nbchar > 0) {
 
3734
                if ((ctxt->sax != NULL) &&
 
3735
                    (ctxt->sax->ignorableWhitespace !=
 
3736
                     ctxt->sax->characters) &&
 
3737
                    (IS_BLANK_CH(*ctxt->input->cur))) {
 
3738
                    const xmlChar *tmp = ctxt->input->cur;
 
3739
                    ctxt->input->cur = in;
 
3740
 
 
3741
                    if (areBlanks(ctxt, tmp, nbchar, 0)) {
 
3742
                        if (ctxt->sax->ignorableWhitespace != NULL)
 
3743
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
 
3744
                                                           tmp, nbchar);
 
3745
                    } else {
 
3746
                        if (ctxt->sax->characters != NULL)
 
3747
                            ctxt->sax->characters(ctxt->userData,
 
3748
                                                  tmp, nbchar);
 
3749
                        if (*ctxt->space == -1)
 
3750
                            *ctxt->space = -2;
 
3751
                    }
 
3752
                    line = ctxt->input->line;
 
3753
                    col = ctxt->input->col;
 
3754
                } else if (ctxt->sax != NULL) {
 
3755
                    if (ctxt->sax->characters != NULL)
 
3756
                        ctxt->sax->characters(ctxt->userData,
 
3757
                                              ctxt->input->cur, nbchar);
 
3758
                    line = ctxt->input->line;
 
3759
                    col = ctxt->input->col;
 
3760
                }
 
3761
            }
 
3762
            ctxt->input->cur = in;
 
3763
            if (*in == 0xD) {
 
3764
                in++;
 
3765
                if (*in == 0xA) {
 
3766
                    ctxt->input->cur = in;
 
3767
                    in++;
 
3768
                    ctxt->input->line++; ctxt->input->col = 1;
 
3769
                    continue; /* while */
 
3770
                }
 
3771
                in--;
 
3772
            }
 
3773
            if (*in == '<') {
 
3774
                return;
 
3775
            }
 
3776
            if (*in == '&') {
 
3777
                return;
 
3778
            }
 
3779
            SHRINK;
 
3780
            GROW;
 
3781
            in = ctxt->input->cur;
 
3782
        } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
 
3783
        nbchar = 0;
 
3784
    }
 
3785
    ctxt->input->line = line;
 
3786
    ctxt->input->col = col;
 
3787
    xmlParseCharDataComplex(ctxt, cdata);
 
3788
}
 
3789
 
 
3790
/**
 
3791
 * xmlParseCharDataComplex:
 
3792
 * @ctxt:  an XML parser context
 
3793
 * @cdata:  int indicating whether we are within a CDATA section
 
3794
 *
 
3795
 * parse a CharData section.this is the fallback function
 
3796
 * of xmlParseCharData() when the parsing requires handling
 
3797
 * of non-ASCII characters.
 
3798
 */
 
3799
void
 
3800
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
 
3801
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
 
3802
    int nbchar = 0;
 
3803
    int cur, l;
 
3804
    int count = 0;
 
3805
 
 
3806
    SHRINK;
 
3807
    GROW;
 
3808
    cur = CUR_CHAR(l);
 
3809
    while ((cur != '<') && /* checked */
 
3810
           (cur != '&') && 
 
3811
           (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
 
3812
        if ((cur == ']') && (NXT(1) == ']') &&
 
3813
            (NXT(2) == '>')) {
 
3814
            if (cdata) break;
 
3815
            else {
 
3816
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 
3817
            }
 
3818
        }
 
3819
        COPY_BUF(l,buf,nbchar,cur);
 
3820
        if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
 
3821
            buf[nbchar] = 0;
 
3822
 
 
3823
            /*
 
3824
             * OK the segment is to be consumed as chars.
 
3825
             */
 
3826
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
3827
                if (areBlanks(ctxt, buf, nbchar, 0)) {
 
3828
                    if (ctxt->sax->ignorableWhitespace != NULL)
 
3829
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
 
3830
                                                       buf, nbchar);
 
3831
                } else {
 
3832
                    if (ctxt->sax->characters != NULL)
 
3833
                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
 
3834
                    if ((ctxt->sax->characters !=
 
3835
                         ctxt->sax->ignorableWhitespace) &&
 
3836
                        (*ctxt->space == -1))
 
3837
                        *ctxt->space = -2;
 
3838
                }
 
3839
            }
 
3840
            nbchar = 0;
 
3841
        }
 
3842
        count++;
 
3843
        if (count > 50) {
 
3844
            GROW;
 
3845
            count = 0;
 
3846
        }
 
3847
        NEXTL(l);
 
3848
        cur = CUR_CHAR(l);
 
3849
    }
 
3850
    if (nbchar != 0) {
 
3851
        buf[nbchar] = 0;
 
3852
        /*
 
3853
         * OK the segment is to be consumed as chars.
 
3854
         */
 
3855
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
3856
            if (areBlanks(ctxt, buf, nbchar, 0)) {
 
3857
                if (ctxt->sax->ignorableWhitespace != NULL)
 
3858
                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
 
3859
            } else {
 
3860
                if (ctxt->sax->characters != NULL)
 
3861
                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
 
3862
                if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
 
3863
                    (*ctxt->space == -1))
 
3864
                    *ctxt->space = -2;
 
3865
            }
 
3866
        }
 
3867
    }
 
3868
    if ((cur != 0) && (!IS_CHAR(cur))) {
 
3869
        /* Generate the error and skip the offending character */
 
3870
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
3871
                          "PCDATA invalid Char value %d\n",
 
3872
                          cur);
 
3873
        NEXTL(l);
 
3874
    }
 
3875
}
 
3876
 
 
3877
/**
 
3878
 * xmlParseExternalID:
 
3879
 * @ctxt:  an XML parser context
 
3880
 * @publicID:  a xmlChar** receiving PubidLiteral
 
3881
 * @strict: indicate whether we should restrict parsing to only
 
3882
 *          production [75], see NOTE below
 
3883
 *
 
3884
 * Parse an External ID or a Public ID
 
3885
 *
 
3886
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
 
3887
 *       'PUBLIC' S PubidLiteral S SystemLiteral
 
3888
 *
 
3889
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
 
3890
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
 
3891
 *
 
3892
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
 
3893
 *
 
3894
 * Returns the function returns SystemLiteral and in the second
 
3895
 *                case publicID receives PubidLiteral, is strict is off
 
3896
 *                it is possible to return NULL and have publicID set.
 
3897
 */
 
3898
 
 
3899
xmlChar *
 
3900
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
 
3901
    xmlChar *URI = NULL;
 
3902
 
 
3903
    SHRINK;
 
3904
 
 
3905
    *publicID = NULL;
 
3906
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
 
3907
        SKIP(6);
 
3908
        if (!IS_BLANK_CH(CUR)) {
 
3909
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
3910
                           "Space required after 'SYSTEM'\n");
 
3911
        }
 
3912
        SKIP_BLANKS;
 
3913
        URI = xmlParseSystemLiteral(ctxt);
 
3914
        if (URI == NULL) {
 
3915
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
 
3916
        }
 
3917
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
 
3918
        SKIP(6);
 
3919
        if (!IS_BLANK_CH(CUR)) {
 
3920
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
3921
                    "Space required after 'PUBLIC'\n");
 
3922
        }
 
3923
        SKIP_BLANKS;
 
3924
        *publicID = xmlParsePubidLiteral(ctxt);
 
3925
        if (*publicID == NULL) {
 
3926
            xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
 
3927
        }
 
3928
        if (strict) {
 
3929
            /*
 
3930
             * We don't handle [83] so "S SystemLiteral" is required.
 
3931
             */
 
3932
            if (!IS_BLANK_CH(CUR)) {
 
3933
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
3934
                        "Space required after the Public Identifier\n");
 
3935
            }
 
3936
        } else {
 
3937
            /*
 
3938
             * We handle [83] so we return immediately, if 
 
3939
             * "S SystemLiteral" is not detected. From a purely parsing
 
3940
             * point of view that's a nice mess.
 
3941
             */
 
3942
            const xmlChar *ptr;
 
3943
            GROW;
 
3944
 
 
3945
            ptr = CUR_PTR;
 
3946
            if (!IS_BLANK_CH(*ptr)) return(NULL);
 
3947
            
 
3948
            while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
 
3949
            if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
 
3950
        }
 
3951
        SKIP_BLANKS;
 
3952
        URI = xmlParseSystemLiteral(ctxt);
 
3953
        if (URI == NULL) {
 
3954
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
 
3955
        }
 
3956
    }
 
3957
    return(URI);
 
3958
}
 
3959
 
 
3960
/**
 
3961
 * xmlParseCommentComplex:
 
3962
 * @ctxt:  an XML parser context
 
3963
 * @buf:  the already parsed part of the buffer
 
3964
 * @len:  number of bytes filles in the buffer
 
3965
 * @size:  allocated size of the buffer
 
3966
 *
 
3967
 * Skip an XML (SGML) comment <!-- .... -->
 
3968
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
 
3969
 *  must not occur within comments. "
 
3970
 * This is the slow routine in case the accelerator for ascii didn't work
 
3971
 *
 
3972
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
 
3973
 */
 
3974
static void
 
3975
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) {
 
3976
    int q, ql;
 
3977
    int r, rl;
 
3978
    int cur, l;
 
3979
    xmlParserInputPtr input = ctxt->input;
 
3980
    int count = 0;
 
3981
 
 
3982
    if (buf == NULL) {
 
3983
        len = 0;
 
3984
        size = XML_PARSER_BUFFER_SIZE;
 
3985
        buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
3986
        if (buf == NULL) {
 
3987
            xmlErrMemory(ctxt, NULL);
 
3988
            return;
 
3989
        }
 
3990
    }
 
3991
    GROW;       /* Assure there's enough input data */
 
3992
    q = CUR_CHAR(ql);
 
3993
    if (q == 0)
 
3994
        goto not_terminated;
 
3995
    if (!IS_CHAR(q)) {
 
3996
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
3997
                          "xmlParseComment: invalid xmlChar value %d\n",
 
3998
                          q);
 
3999
        xmlFree (buf);
 
4000
        return;
 
4001
    }
 
4002
    NEXTL(ql);
 
4003
    r = CUR_CHAR(rl);
 
4004
    if (r == 0)
 
4005
        goto not_terminated;
 
4006
    if (!IS_CHAR(r)) {
 
4007
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4008
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4009
                          q);
 
4010
        xmlFree (buf);
 
4011
        return;
 
4012
    }
 
4013
    NEXTL(rl);
 
4014
    cur = CUR_CHAR(l);
 
4015
    if (cur == 0)
 
4016
        goto not_terminated;
 
4017
    while (IS_CHAR(cur) && /* checked */
 
4018
           ((cur != '>') ||
 
4019
            (r != '-') || (q != '-'))) {
 
4020
        if ((r == '-') && (q == '-')) {
 
4021
            xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
 
4022
        }
 
4023
        if (len + 5 >= size) {
 
4024
            xmlChar *new_buf;
 
4025
            size *= 2;
 
4026
            new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
4027
            if (new_buf == NULL) {
 
4028
                xmlFree (buf);
 
4029
                xmlErrMemory(ctxt, NULL);
 
4030
                return;
 
4031
            }
 
4032
            buf = new_buf;
 
4033
        }
 
4034
        COPY_BUF(ql,buf,len,q);
 
4035
        q = r;
 
4036
        ql = rl;
 
4037
        r = cur;
 
4038
        rl = l;
 
4039
 
 
4040
        count++;
 
4041
        if (count > 50) {
 
4042
            GROW;
 
4043
            count = 0;
 
4044
        }
 
4045
        NEXTL(l);
 
4046
        cur = CUR_CHAR(l);
 
4047
        if (cur == 0) {
 
4048
            SHRINK;
 
4049
            GROW;
 
4050
            cur = CUR_CHAR(l);
 
4051
        }
 
4052
    }
 
4053
    buf[len] = 0;
 
4054
    if (cur == 0) {
 
4055
        xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4056
                             "Comment not terminated \n<!--%.50s\n", buf);
 
4057
    } else if (!IS_CHAR(cur)) {
 
4058
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4059
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4060
                          cur);
 
4061
    } else {
 
4062
        if (input != ctxt->input) {
 
4063
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
4064
                "Comment doesn't start and stop in the same entity\n");
 
4065
        }
 
4066
        NEXT;
 
4067
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 
4068
            (!ctxt->disableSAX))
 
4069
            ctxt->sax->comment(ctxt->userData, buf);
 
4070
    }
 
4071
    xmlFree(buf);
 
4072
    return;
 
4073
not_terminated:
 
4074
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4075
                         "Comment not terminated\n", NULL);
 
4076
    xmlFree(buf);
 
4077
    return;
 
4078
}
 
4079
 
 
4080
/**
 
4081
 * xmlParseComment:
 
4082
 * @ctxt:  an XML parser context
 
4083
 *
 
4084
 * Skip an XML (SGML) comment <!-- .... -->
 
4085
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
 
4086
 *  must not occur within comments. "
 
4087
 *
 
4088
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
 
4089
 */
 
4090
void
 
4091
xmlParseComment(xmlParserCtxtPtr ctxt) {
 
4092
    xmlChar *buf = NULL;
 
4093
    int size = XML_PARSER_BUFFER_SIZE;
 
4094
    int len = 0;
 
4095
    xmlParserInputState state;
 
4096
    const xmlChar *in;
 
4097
    int nbchar = 0, ccol;
 
4098
 
 
4099
    /*
 
4100
     * Check that there is a comment right here.
 
4101
     */
 
4102
    if ((RAW != '<') || (NXT(1) != '!') ||
 
4103
        (NXT(2) != '-') || (NXT(3) != '-')) return;
 
4104
 
 
4105
    state = ctxt->instate;
 
4106
    ctxt->instate = XML_PARSER_COMMENT;
 
4107
    SKIP(4);
 
4108
    SHRINK;
 
4109
    GROW;
 
4110
 
 
4111
    /*
 
4112
     * Accelerated common case where input don't need to be
 
4113
     * modified before passing it to the handler.
 
4114
     */
 
4115
    in = ctxt->input->cur;
 
4116
    do {
 
4117
        if (*in == 0xA) {
 
4118
            do {
 
4119
                ctxt->input->line++; ctxt->input->col = 1;
 
4120
                in++;
 
4121
            } while (*in == 0xA);
 
4122
        }
 
4123
get_more:
 
4124
        ccol = ctxt->input->col;
 
4125
        while (((*in > '-') && (*in <= 0x7F)) ||
 
4126
               ((*in >= 0x20) && (*in < '-')) ||
 
4127
               (*in == 0x09)) {
 
4128
                    in++;
 
4129
                    ccol++;
 
4130
        }
 
4131
        ctxt->input->col = ccol;
 
4132
        if (*in == 0xA) {
 
4133
            do {
 
4134
                ctxt->input->line++; ctxt->input->col = 1;
 
4135
                in++;
 
4136
            } while (*in == 0xA);
 
4137
            goto get_more;
 
4138
        }
 
4139
        nbchar = in - ctxt->input->cur;
 
4140
        /*
 
4141
         * save current set of data
 
4142
         */
 
4143
        if (nbchar > 0) {
 
4144
            if ((ctxt->sax != NULL) &&
 
4145
                (ctxt->sax->comment != NULL)) {
 
4146
                if (buf == NULL) {
 
4147
                    if ((*in == '-') && (in[1] == '-'))
 
4148
                        size = nbchar + 1;
 
4149
                    else
 
4150
                        size = XML_PARSER_BUFFER_SIZE + nbchar;
 
4151
                    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4152
                    if (buf == NULL) {
 
4153
                        xmlErrMemory(ctxt, NULL);
 
4154
                        ctxt->instate = state;
 
4155
                        return;
 
4156
                    }
 
4157
                    len = 0;
 
4158
                } else if (len + nbchar + 1 >= size) {
 
4159
                    xmlChar *new_buf;
 
4160
                    size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
 
4161
                    new_buf = (xmlChar *) xmlRealloc(buf,
 
4162
                                                     size * sizeof(xmlChar));
 
4163
                    if (new_buf == NULL) {
 
4164
                        xmlFree (buf);
 
4165
                        xmlErrMemory(ctxt, NULL);
 
4166
                        ctxt->instate = state;
 
4167
                        return;
 
4168
                    }
 
4169
                    buf = new_buf;
 
4170
                }
 
4171
                memcpy(&buf[len], ctxt->input->cur, nbchar);
 
4172
                len += nbchar;
 
4173
                buf[len] = 0;
 
4174
            }
 
4175
        }
 
4176
        ctxt->input->cur = in;
 
4177
        if (*in == 0xA) {
 
4178
            in++;
 
4179
            ctxt->input->line++; ctxt->input->col = 1;
 
4180
        }
 
4181
        if (*in == 0xD) {
 
4182
            in++;
 
4183
            if (*in == 0xA) {
 
4184
                ctxt->input->cur = in;
 
4185
                in++;
 
4186
                ctxt->input->line++; ctxt->input->col = 1;
 
4187
                continue; /* while */
 
4188
            }
 
4189
            in--;
 
4190
        }
 
4191
        SHRINK;
 
4192
        GROW;
 
4193
        in = ctxt->input->cur;
 
4194
        if (*in == '-') {
 
4195
            if (in[1] == '-') {
 
4196
                if (in[2] == '>') {
 
4197
                    SKIP(3);
 
4198
                    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 
4199
                        (!ctxt->disableSAX)) {
 
4200
                        if (buf != NULL)
 
4201
                            ctxt->sax->comment(ctxt->userData, buf);
 
4202
                        else
 
4203
                            ctxt->sax->comment(ctxt->userData, BAD_CAST "");
 
4204
                    }
 
4205
                    if (buf != NULL)
 
4206
                        xmlFree(buf);
 
4207
                    ctxt->instate = state;
 
4208
                    return;
 
4209
                }
 
4210
                if (buf != NULL)
 
4211
                    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4212
                                      "Comment not terminated \n<!--%.50s\n",
 
4213
                                      buf);
 
4214
                else
 
4215
                    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4216
                                      "Comment not terminated \n", NULL);
 
4217
                in++;
 
4218
                ctxt->input->col++;
 
4219
            }
 
4220
            in++;
 
4221
            ctxt->input->col++;
 
4222
            goto get_more;
 
4223
        }
 
4224
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
 
4225
    xmlParseCommentComplex(ctxt, buf, len, size);
 
4226
    ctxt->instate = state;
 
4227
    return;
 
4228
}
 
4229
 
 
4230
 
 
4231
/**
 
4232
 * xmlParsePITarget:
 
4233
 * @ctxt:  an XML parser context
 
4234
 * 
 
4235
 * parse the name of a PI
 
4236
 *
 
4237
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
 
4238
 *
 
4239
 * Returns the PITarget name or NULL
 
4240
 */
 
4241
 
 
4242
const xmlChar *
 
4243
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
 
4244
    const xmlChar *name;
 
4245
 
 
4246
    name = xmlParseName(ctxt);
 
4247
    if ((name != NULL) &&
 
4248
        ((name[0] == 'x') || (name[0] == 'X')) &&
 
4249
        ((name[1] == 'm') || (name[1] == 'M')) &&
 
4250
        ((name[2] == 'l') || (name[2] == 'L'))) {
 
4251
        int i;
 
4252
        if ((name[0] == 'x') && (name[1] == 'm') &&
 
4253
            (name[2] == 'l') && (name[3] == 0)) {
 
4254
            xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
 
4255
                 "XML declaration allowed only at the start of the document\n");
 
4256
            return(name);
 
4257
        } else if (name[3] == 0) {
 
4258
            xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
 
4259
            return(name);
 
4260
        }
 
4261
        for (i = 0;;i++) {
 
4262
            if (xmlW3CPIs[i] == NULL) break;
 
4263
            if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
 
4264
                return(name);
 
4265
        }
 
4266
        xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
 
4267
                      "xmlParsePITarget: invalid name prefix 'xml'\n",
 
4268
                      NULL, NULL);
 
4269
    }
 
4270
    return(name);
 
4271
}
 
4272
 
 
4273
#ifdef LIBXML_CATALOG_ENABLED
 
4274
/**
 
4275
 * xmlParseCatalogPI:
 
4276
 * @ctxt:  an XML parser context
 
4277
 * @catalog:  the PI value string
 
4278
 * 
 
4279
 * parse an XML Catalog Processing Instruction.
 
4280
 *
 
4281
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
 
4282
 *
 
4283
 * Occurs only if allowed by the user and if happening in the Misc
 
4284
 * part of the document before any doctype informations
 
4285
 * This will add the given catalog to the parsing context in order
 
4286
 * to be used if there is a resolution need further down in the document
 
4287
 */
 
4288
 
 
4289
static void
 
4290
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
 
4291
    xmlChar *URL = NULL;
 
4292
    const xmlChar *tmp, *base;
 
4293
    xmlChar marker;
 
4294
 
 
4295
    tmp = catalog;
 
4296
    while (IS_BLANK_CH(*tmp)) tmp++;
 
4297
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
 
4298
        goto error;
 
4299
    tmp += 7;
 
4300
    while (IS_BLANK_CH(*tmp)) tmp++;
 
4301
    if (*tmp != '=') {
 
4302
        return;
 
4303
    }
 
4304
    tmp++;
 
4305
    while (IS_BLANK_CH(*tmp)) tmp++;
 
4306
    marker = *tmp;
 
4307
    if ((marker != '\'') && (marker != '"'))
 
4308
        goto error;
 
4309
    tmp++;
 
4310
    base = tmp;
 
4311
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
 
4312
    if (*tmp == 0)
 
4313
        goto error;
 
4314
    URL = xmlStrndup(base, tmp - base);
 
4315
    tmp++;
 
4316
    while (IS_BLANK_CH(*tmp)) tmp++;
 
4317
    if (*tmp != 0)
 
4318
        goto error;
 
4319
 
 
4320
    if (URL != NULL) {
 
4321
        ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
 
4322
        xmlFree(URL);
 
4323
    }
 
4324
    return;
 
4325
 
 
4326
error:
 
4327
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
 
4328
                  "Catalog PI syntax error: %s\n",
 
4329
                  catalog, NULL);
 
4330
    if (URL != NULL)
 
4331
        xmlFree(URL);
 
4332
}
 
4333
#endif
 
4334
 
 
4335
/**
 
4336
 * xmlParsePI:
 
4337
 * @ctxt:  an XML parser context
 
4338
 * 
 
4339
 * parse an XML Processing Instruction.
 
4340
 *
 
4341
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
 
4342
 *
 
4343
 * The processing is transfered to SAX once parsed.
 
4344
 */
 
4345
 
 
4346
void
 
4347
xmlParsePI(xmlParserCtxtPtr ctxt) {
 
4348
    xmlChar *buf = NULL;
 
4349
    int len = 0;
 
4350
    int size = XML_PARSER_BUFFER_SIZE;
 
4351
    int cur, l;
 
4352
    const xmlChar *target;
 
4353
    xmlParserInputState state;
 
4354
    int count = 0;
 
4355
 
 
4356
    if ((RAW == '<') && (NXT(1) == '?')) {
 
4357
        xmlParserInputPtr input = ctxt->input;
 
4358
        state = ctxt->instate;
 
4359
        ctxt->instate = XML_PARSER_PI;
 
4360
        /*
 
4361
         * this is a Processing Instruction.
 
4362
         */
 
4363
        SKIP(2);
 
4364
        SHRINK;
 
4365
 
 
4366
        /*
 
4367
         * Parse the target name and check for special support like
 
4368
         * namespace.
 
4369
         */
 
4370
        target = xmlParsePITarget(ctxt);
 
4371
        if (target != NULL) {
 
4372
            if ((RAW == '?') && (NXT(1) == '>')) {
 
4373
                if (input != ctxt->input) {
 
4374
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
4375
            "PI declaration doesn't start and stop in the same entity\n");
 
4376
                }
 
4377
                SKIP(2);
 
4378
 
 
4379
                /*
 
4380
                 * SAX: PI detected.
 
4381
                 */
 
4382
                if ((ctxt->sax) && (!ctxt->disableSAX) &&
 
4383
                    (ctxt->sax->processingInstruction != NULL))
 
4384
                    ctxt->sax->processingInstruction(ctxt->userData,
 
4385
                                                     target, NULL);
 
4386
                ctxt->instate = state;
 
4387
                return;
 
4388
            }
 
4389
            buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4390
            if (buf == NULL) {
 
4391
                xmlErrMemory(ctxt, NULL);
 
4392
                ctxt->instate = state;
 
4393
                return;
 
4394
            }
 
4395
            cur = CUR;
 
4396
            if (!IS_BLANK(cur)) {
 
4397
                xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
 
4398
                          "ParsePI: PI %s space expected\n", target);
 
4399
            }
 
4400
            SKIP_BLANKS;
 
4401
            cur = CUR_CHAR(l);
 
4402
            while (IS_CHAR(cur) && /* checked */
 
4403
                   ((cur != '?') || (NXT(1) != '>'))) {
 
4404
                if (len + 5 >= size) {
 
4405
                    xmlChar *tmp;
 
4406
 
 
4407
                    size *= 2;
 
4408
                    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
4409
                    if (tmp == NULL) {
 
4410
                        xmlErrMemory(ctxt, NULL);
 
4411
                        xmlFree(buf);
 
4412
                        ctxt->instate = state;
 
4413
                        return;
 
4414
                    }
 
4415
                    buf = tmp;
 
4416
                }
 
4417
                count++;
 
4418
                if (count > 50) {
 
4419
                    GROW;
 
4420
                    count = 0;
 
4421
                }
 
4422
                COPY_BUF(l,buf,len,cur);
 
4423
                NEXTL(l);
 
4424
                cur = CUR_CHAR(l);
 
4425
                if (cur == 0) {
 
4426
                    SHRINK;
 
4427
                    GROW;
 
4428
                    cur = CUR_CHAR(l);
 
4429
                }
 
4430
            }
 
4431
            buf[len] = 0;
 
4432
            if (cur != '?') {
 
4433
                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
4434
                      "ParsePI: PI %s never end ...\n", target);
 
4435
            } else {
 
4436
                if (input != ctxt->input) {
 
4437
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4438
            "PI declaration doesn't start and stop in the same entity\n");
 
4439
                }
 
4440
                SKIP(2);
 
4441
 
 
4442
#ifdef LIBXML_CATALOG_ENABLED
 
4443
                if (((state == XML_PARSER_MISC) ||
 
4444
                     (state == XML_PARSER_START)) &&
 
4445
                    (xmlStrEqual(target, XML_CATALOG_PI))) {
 
4446
                    xmlCatalogAllow allow = xmlCatalogGetDefaults();
 
4447
                    if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
 
4448
                        (allow == XML_CATA_ALLOW_ALL))
 
4449
                        xmlParseCatalogPI(ctxt, buf);
 
4450
                }
 
4451
#endif
 
4452
 
 
4453
 
 
4454
                /*
 
4455
                 * SAX: PI detected.
 
4456
                 */
 
4457
                if ((ctxt->sax) && (!ctxt->disableSAX) &&
 
4458
                    (ctxt->sax->processingInstruction != NULL))
 
4459
                    ctxt->sax->processingInstruction(ctxt->userData,
 
4460
                                                     target, buf);
 
4461
            }
 
4462
            xmlFree(buf);
 
4463
        } else {
 
4464
            xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
 
4465
        }
 
4466
        ctxt->instate = state;
 
4467
    }
 
4468
}
 
4469
 
 
4470
/**
 
4471
 * xmlParseNotationDecl:
 
4472
 * @ctxt:  an XML parser context
 
4473
 *
 
4474
 * parse a notation declaration
 
4475
 *
 
4476
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
 
4477
 *
 
4478
 * Hence there is actually 3 choices:
 
4479
 *     'PUBLIC' S PubidLiteral
 
4480
 *     'PUBLIC' S PubidLiteral S SystemLiteral
 
4481
 * and 'SYSTEM' S SystemLiteral
 
4482
 *
 
4483
 * See the NOTE on xmlParseExternalID().
 
4484
 */
 
4485
 
 
4486
void
 
4487
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
 
4488
    const xmlChar *name;
 
4489
    xmlChar *Pubid;
 
4490
    xmlChar *Systemid;
 
4491
    
 
4492
    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 
4493
        xmlParserInputPtr input = ctxt->input;
 
4494
        SHRINK;
 
4495
        SKIP(10);
 
4496
        if (!IS_BLANK_CH(CUR)) {
 
4497
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4498
                           "Space required after '<!NOTATION'\n");
 
4499
            return;
 
4500
        }
 
4501
        SKIP_BLANKS;
 
4502
 
 
4503
        name = xmlParseName(ctxt);
 
4504
        if (name == NULL) {
 
4505
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 
4506
            return;
 
4507
        }
 
4508
        if (!IS_BLANK_CH(CUR)) {
 
4509
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4510
                     "Space required after the NOTATION name'\n");
 
4511
            return;
 
4512
        }
 
4513
        SKIP_BLANKS;
 
4514
 
 
4515
        /*
 
4516
         * Parse the IDs.
 
4517
         */
 
4518
        Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
 
4519
        SKIP_BLANKS;
 
4520
 
 
4521
        if (RAW == '>') {
 
4522
            if (input != ctxt->input) {
 
4523
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4524
        "Notation declaration doesn't start and stop in the same entity\n");
 
4525
            }
 
4526
            NEXT;
 
4527
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
4528
                (ctxt->sax->notationDecl != NULL))
 
4529
                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
 
4530
        } else {
 
4531
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
 
4532
        }
 
4533
        if (Systemid != NULL) xmlFree(Systemid);
 
4534
        if (Pubid != NULL) xmlFree(Pubid);
 
4535
    }
 
4536
}
 
4537
 
 
4538
/**
 
4539
 * xmlParseEntityDecl:
 
4540
 * @ctxt:  an XML parser context
 
4541
 *
 
4542
 * parse <!ENTITY declarations
 
4543
 *
 
4544
 * [70] EntityDecl ::= GEDecl | PEDecl
 
4545
 *
 
4546
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
 
4547
 *
 
4548
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
 
4549
 *
 
4550
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
 
4551
 *
 
4552
 * [74] PEDef ::= EntityValue | ExternalID
 
4553
 *
 
4554
 * [76] NDataDecl ::= S 'NDATA' S Name
 
4555
 *
 
4556
 * [ VC: Notation Declared ]
 
4557
 * The Name must match the declared name of a notation.
 
4558
 */
 
4559
 
 
4560
void
 
4561
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 
4562
    const xmlChar *name = NULL;
 
4563
    xmlChar *value = NULL;
 
4564
    xmlChar *URI = NULL, *literal = NULL;
 
4565
    const xmlChar *ndata = NULL;
 
4566
    int isParameter = 0;
 
4567
    xmlChar *orig = NULL;
 
4568
    int skipped;
 
4569
    
 
4570
    /* GROW; done in the caller */
 
4571
    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
 
4572
        xmlParserInputPtr input = ctxt->input;
 
4573
        SHRINK;
 
4574
        SKIP(8);
 
4575
        skipped = SKIP_BLANKS;
 
4576
        if (skipped == 0) {
 
4577
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4578
                           "Space required after '<!ENTITY'\n");
 
4579
        }
 
4580
 
 
4581
        if (RAW == '%') {
 
4582
            NEXT;
 
4583
            skipped = SKIP_BLANKS;
 
4584
            if (skipped == 0) {
 
4585
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4586
                               "Space required after '%'\n");
 
4587
            }
 
4588
            isParameter = 1;
 
4589
        }
 
4590
 
 
4591
        name = xmlParseName(ctxt);
 
4592
        if (name == NULL) {
 
4593
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
4594
                           "xmlParseEntityDecl: no name\n");
 
4595
            return;
 
4596
        }
 
4597
        skipped = SKIP_BLANKS;
 
4598
        if (skipped == 0) {
 
4599
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4600
                           "Space required after the entity name\n");
 
4601
        }
 
4602
 
 
4603
        ctxt->instate = XML_PARSER_ENTITY_DECL;
 
4604
        /*
 
4605
         * handle the various case of definitions...
 
4606
         */
 
4607
        if (isParameter) {
 
4608
            if ((RAW == '"') || (RAW == '\'')) {
 
4609
                value = xmlParseEntityValue(ctxt, &orig);
 
4610
                if (value) {
 
4611
                    if ((ctxt->sax != NULL) &&
 
4612
                        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
4613
                        ctxt->sax->entityDecl(ctxt->userData, name,
 
4614
                                    XML_INTERNAL_PARAMETER_ENTITY,
 
4615
                                    NULL, NULL, value);
 
4616
                }
 
4617
            } else {
 
4618
                URI = xmlParseExternalID(ctxt, &literal, 1);
 
4619
                if ((URI == NULL) && (literal == NULL)) {
 
4620
                    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 
4621
                }
 
4622
                if (URI) {
 
4623
                    xmlURIPtr uri;
 
4624
 
 
4625
                    uri = xmlParseURI((const char *) URI);
 
4626
                    if (uri == NULL) {
 
4627
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
 
4628
                                     "Invalid URI: %s\n", URI);
 
4629
                        /*
 
4630
                         * This really ought to be a well formedness error
 
4631
                         * but the XML Core WG decided otherwise c.f. issue
 
4632
                         * E26 of the XML erratas.
 
4633
                         */
 
4634
                    } else {
 
4635
                        if (uri->fragment != NULL) {
 
4636
                            /*
 
4637
                             * Okay this is foolish to block those but not
 
4638
                             * invalid URIs.
 
4639
                             */
 
4640
                            xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
 
4641
                        } else {
 
4642
                            if ((ctxt->sax != NULL) &&
 
4643
                                (!ctxt->disableSAX) &&
 
4644
                                (ctxt->sax->entityDecl != NULL))
 
4645
                                ctxt->sax->entityDecl(ctxt->userData, name,
 
4646
                                            XML_EXTERNAL_PARAMETER_ENTITY,
 
4647
                                            literal, URI, NULL);
 
4648
                        }
 
4649
                        xmlFreeURI(uri);
 
4650
                    }
 
4651
                }
 
4652
            }
 
4653
        } else {
 
4654
            if ((RAW == '"') || (RAW == '\'')) {
 
4655
                value = xmlParseEntityValue(ctxt, &orig);
 
4656
                if ((ctxt->sax != NULL) &&
 
4657
                    (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
4658
                    ctxt->sax->entityDecl(ctxt->userData, name,
 
4659
                                XML_INTERNAL_GENERAL_ENTITY,
 
4660
                                NULL, NULL, value);
 
4661
                /*
 
4662
                 * For expat compatibility in SAX mode.
 
4663
                 */
 
4664
                if ((ctxt->myDoc == NULL) ||
 
4665
                    (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
 
4666
                    if (ctxt->myDoc == NULL) {
 
4667
                        ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 
4668
                        if (ctxt->myDoc == NULL) {
 
4669
                            xmlErrMemory(ctxt, "New Doc failed");
 
4670
                            return;
 
4671
                        }
 
4672
                    }
 
4673
                    if (ctxt->myDoc->intSubset == NULL)
 
4674
                        ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 
4675
                                            BAD_CAST "fake", NULL, NULL);
 
4676
 
 
4677
                    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
 
4678
                                      NULL, NULL, value);
 
4679
                }
 
4680
            } else {
 
4681
                URI = xmlParseExternalID(ctxt, &literal, 1);
 
4682
                if ((URI == NULL) && (literal == NULL)) {
 
4683
                    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 
4684
                }
 
4685
                if (URI) {
 
4686
                    xmlURIPtr uri;
 
4687
 
 
4688
                    uri = xmlParseURI((const char *)URI);
 
4689
                    if (uri == NULL) {
 
4690
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
 
4691
                                     "Invalid URI: %s\n", URI);
 
4692
                        /*
 
4693
                         * This really ought to be a well formedness error
 
4694
                         * but the XML Core WG decided otherwise c.f. issue
 
4695
                         * E26 of the XML erratas.
 
4696
                         */
 
4697
                    } else {
 
4698
                        if (uri->fragment != NULL) {
 
4699
                            /*
 
4700
                             * Okay this is foolish to block those but not
 
4701
                             * invalid URIs.
 
4702
                             */
 
4703
                            xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
 
4704
                        }
 
4705
                        xmlFreeURI(uri);
 
4706
                    }
 
4707
                }
 
4708
                if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
 
4709
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4710
                                   "Space required before 'NDATA'\n");
 
4711
                }
 
4712
                SKIP_BLANKS;
 
4713
                if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
 
4714
                    SKIP(5);
 
4715
                    if (!IS_BLANK_CH(CUR)) {
 
4716
                        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4717
                                       "Space required after 'NDATA'\n");
 
4718
                    }
 
4719
                    SKIP_BLANKS;
 
4720
                    ndata = xmlParseName(ctxt);
 
4721
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
4722
                        (ctxt->sax->unparsedEntityDecl != NULL))
 
4723
                        ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
 
4724
                                    literal, URI, ndata);
 
4725
                } else {
 
4726
                    if ((ctxt->sax != NULL) &&
 
4727
                        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
4728
                        ctxt->sax->entityDecl(ctxt->userData, name,
 
4729
                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 
4730
                                    literal, URI, NULL);
 
4731
                    /*
 
4732
                     * For expat compatibility in SAX mode.
 
4733
                     * assuming the entity repalcement was asked for
 
4734
                     */
 
4735
                    if ((ctxt->replaceEntities != 0) &&
 
4736
                        ((ctxt->myDoc == NULL) ||
 
4737
                        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
 
4738
                        if (ctxt->myDoc == NULL) {
 
4739
                            ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 
4740
                            if (ctxt->myDoc == NULL) {
 
4741
                                xmlErrMemory(ctxt, "New Doc failed");
 
4742
                                return;
 
4743
                            }
 
4744
                        }
 
4745
 
 
4746
                        if (ctxt->myDoc->intSubset == NULL)
 
4747
                            ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 
4748
                                                BAD_CAST "fake", NULL, NULL);
 
4749
                        xmlSAX2EntityDecl(ctxt, name,
 
4750
                                          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 
4751
                                          literal, URI, NULL);
 
4752
                    }
 
4753
                }
 
4754
            }
 
4755
        }
 
4756
        SKIP_BLANKS;
 
4757
        if (RAW != '>') {
 
4758
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
 
4759
                    "xmlParseEntityDecl: entity %s not terminated\n", name);
 
4760
        } else {
 
4761
            if (input != ctxt->input) {
 
4762
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
4763
        "Entity declaration doesn't start and stop in the same entity\n");
 
4764
            }
 
4765
            NEXT;
 
4766
        }
 
4767
        if (orig != NULL) {
 
4768
            /*
 
4769
             * Ugly mechanism to save the raw entity value.
 
4770
             */
 
4771
            xmlEntityPtr cur = NULL;
 
4772
 
 
4773
            if (isParameter) {
 
4774
                if ((ctxt->sax != NULL) &&
 
4775
                    (ctxt->sax->getParameterEntity != NULL))
 
4776
                    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
4777
            } else {
 
4778
                if ((ctxt->sax != NULL) &&
 
4779
                    (ctxt->sax->getEntity != NULL))
 
4780
                    cur = ctxt->sax->getEntity(ctxt->userData, name);
 
4781
                if ((cur == NULL) && (ctxt->userData==ctxt)) {
 
4782
                    cur = xmlSAX2GetEntity(ctxt, name);
 
4783
                }
 
4784
            }
 
4785
            if (cur != NULL) {
 
4786
                if (cur->orig != NULL)
 
4787
                    xmlFree(orig);
 
4788
                else
 
4789
                    cur->orig = orig;
 
4790
            } else
 
4791
                xmlFree(orig);
 
4792
        }
 
4793
        if (value != NULL) xmlFree(value);
 
4794
        if (URI != NULL) xmlFree(URI);
 
4795
        if (literal != NULL) xmlFree(literal);
 
4796
    }
 
4797
}
 
4798
 
 
4799
/**
 
4800
 * xmlParseDefaultDecl:
 
4801
 * @ctxt:  an XML parser context
 
4802
 * @value:  Receive a possible fixed default value for the attribute
 
4803
 *
 
4804
 * Parse an attribute default declaration
 
4805
 *
 
4806
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
 
4807
 *
 
4808
 * [ VC: Required Attribute ]
 
4809
 * if the default declaration is the keyword #REQUIRED, then the
 
4810
 * attribute must be specified for all elements of the type in the
 
4811
 * attribute-list declaration.
 
4812
 *
 
4813
 * [ VC: Attribute Default Legal ]
 
4814
 * The declared default value must meet the lexical constraints of
 
4815
 * the declared attribute type c.f. xmlValidateAttributeDecl()
 
4816
 *
 
4817
 * [ VC: Fixed Attribute Default ]
 
4818
 * if an attribute has a default value declared with the #FIXED
 
4819
 * keyword, instances of that attribute must match the default value. 
 
4820
 *
 
4821
 * [ WFC: No < in Attribute Values ]
 
4822
 * handled in xmlParseAttValue()
 
4823
 *
 
4824
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
 
4825
 *          or XML_ATTRIBUTE_FIXED. 
 
4826
 */
 
4827
 
 
4828
int
 
4829
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
 
4830
    int val;
 
4831
    xmlChar *ret;
 
4832
 
 
4833
    *value = NULL;
 
4834
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
 
4835
        SKIP(9);
 
4836
        return(XML_ATTRIBUTE_REQUIRED);
 
4837
    }
 
4838
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
 
4839
        SKIP(8);
 
4840
        return(XML_ATTRIBUTE_IMPLIED);
 
4841
    }
 
4842
    val = XML_ATTRIBUTE_NONE;
 
4843
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
 
4844
        SKIP(6);
 
4845
        val = XML_ATTRIBUTE_FIXED;
 
4846
        if (!IS_BLANK_CH(CUR)) {
 
4847
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4848
                           "Space required after '#FIXED'\n");
 
4849
        }
 
4850
        SKIP_BLANKS;
 
4851
    }
 
4852
    ret = xmlParseAttValue(ctxt);
 
4853
    ctxt->instate = XML_PARSER_DTD;
 
4854
    if (ret == NULL) {
 
4855
        xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
 
4856
                       "Attribute default value declaration error\n");
 
4857
    } else
 
4858
        *value = ret;
 
4859
    return(val);
 
4860
}
 
4861
 
 
4862
/**
 
4863
 * xmlParseNotationType:
 
4864
 * @ctxt:  an XML parser context
 
4865
 *
 
4866
 * parse an Notation attribute type.
 
4867
 *
 
4868
 * Note: the leading 'NOTATION' S part has already being parsed...
 
4869
 *
 
4870
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
 
4871
 *
 
4872
 * [ VC: Notation Attributes ]
 
4873
 * Values of this type must match one of the notation names included
 
4874
 * in the declaration; all notation names in the declaration must be declared. 
 
4875
 *
 
4876
 * Returns: the notation attribute tree built while parsing
 
4877
 */
 
4878
 
 
4879
xmlEnumerationPtr
 
4880
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 
4881
    const xmlChar *name;
 
4882
    xmlEnumerationPtr ret = NULL, last = NULL, cur;
 
4883
 
 
4884
    if (RAW != '(') {
 
4885
        xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 
4886
        return(NULL);
 
4887
    }
 
4888
    SHRINK;
 
4889
    do {
 
4890
        NEXT;
 
4891
        SKIP_BLANKS;
 
4892
        name = xmlParseName(ctxt);
 
4893
        if (name == NULL) {
 
4894
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
4895
                           "Name expected in NOTATION declaration\n");
 
4896
            return(ret);
 
4897
        }
 
4898
        cur = xmlCreateEnumeration(name);
 
4899
        if (cur == NULL) return(ret);
 
4900
        if (last == NULL) ret = last = cur;
 
4901
        else {
 
4902
            last->next = cur;
 
4903
            last = cur;
 
4904
        }
 
4905
        SKIP_BLANKS;
 
4906
    } while (RAW == '|');
 
4907
    if (RAW != ')') {
 
4908
        xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
 
4909
        if ((last != NULL) && (last != ret))
 
4910
            xmlFreeEnumeration(last);
 
4911
        return(ret);
 
4912
    }
 
4913
    NEXT;
 
4914
    return(ret);
 
4915
}
 
4916
 
 
4917
/**
 
4918
 * xmlParseEnumerationType:
 
4919
 * @ctxt:  an XML parser context
 
4920
 *
 
4921
 * parse an Enumeration attribute type.
 
4922
 *
 
4923
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
 
4924
 *
 
4925
 * [ VC: Enumeration ]
 
4926
 * Values of this type must match one of the Nmtoken tokens in
 
4927
 * the declaration
 
4928
 *
 
4929
 * Returns: the enumeration attribute tree built while parsing
 
4930
 */
 
4931
 
 
4932
xmlEnumerationPtr
 
4933
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 
4934
    xmlChar *name;
 
4935
    xmlEnumerationPtr ret = NULL, last = NULL, cur;
 
4936
 
 
4937
    if (RAW != '(') {
 
4938
        xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
 
4939
        return(NULL);
 
4940
    }
 
4941
    SHRINK;
 
4942
    do {
 
4943
        NEXT;
 
4944
        SKIP_BLANKS;
 
4945
        name = xmlParseNmtoken(ctxt);
 
4946
        if (name == NULL) {
 
4947
            xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
 
4948
            return(ret);
 
4949
        }
 
4950
        cur = xmlCreateEnumeration(name);
 
4951
        xmlFree(name);
 
4952
        if (cur == NULL) return(ret);
 
4953
        if (last == NULL) ret = last = cur;
 
4954
        else {
 
4955
            last->next = cur;
 
4956
            last = cur;
 
4957
        }
 
4958
        SKIP_BLANKS;
 
4959
    } while (RAW == '|');
 
4960
    if (RAW != ')') {
 
4961
        xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
 
4962
        return(ret);
 
4963
    }
 
4964
    NEXT;
 
4965
    return(ret);
 
4966
}
 
4967
 
 
4968
/**
 
4969
 * xmlParseEnumeratedType:
 
4970
 * @ctxt:  an XML parser context
 
4971
 * @tree:  the enumeration tree built while parsing
 
4972
 *
 
4973
 * parse an Enumerated attribute type.
 
4974
 *
 
4975
 * [57] EnumeratedType ::= NotationType | Enumeration
 
4976
 *
 
4977
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
 
4978
 *
 
4979
 *
 
4980
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
 
4981
 */
 
4982
 
 
4983
int
 
4984
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
 
4985
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 
4986
        SKIP(8);
 
4987
        if (!IS_BLANK_CH(CUR)) {
 
4988
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4989
                           "Space required after 'NOTATION'\n");
 
4990
            return(0);
 
4991
        }
 
4992
        SKIP_BLANKS;
 
4993
        *tree = xmlParseNotationType(ctxt);
 
4994
        if (*tree == NULL) return(0);
 
4995
        return(XML_ATTRIBUTE_NOTATION);
 
4996
    }
 
4997
    *tree = xmlParseEnumerationType(ctxt);
 
4998
    if (*tree == NULL) return(0);
 
4999
    return(XML_ATTRIBUTE_ENUMERATION);
 
5000
}
 
5001
 
 
5002
/**
 
5003
 * xmlParseAttributeType:
 
5004
 * @ctxt:  an XML parser context
 
5005
 * @tree:  the enumeration tree built while parsing
 
5006
 *
 
5007
 * parse the Attribute list def for an element
 
5008
 *
 
5009
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
 
5010
 *
 
5011
 * [55] StringType ::= 'CDATA'
 
5012
 *
 
5013
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
 
5014
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
 
5015
 *
 
5016
 * Validity constraints for attribute values syntax are checked in
 
5017
 * xmlValidateAttributeValue()
 
5018
 *
 
5019
 * [ VC: ID ]
 
5020
 * Values of type ID must match the Name production. A name must not
 
5021
 * appear more than once in an XML document as a value of this type;
 
5022
 * i.e., ID values must uniquely identify the elements which bear them.
 
5023
 *
 
5024
 * [ VC: One ID per Element Type ]
 
5025
 * No element type may have more than one ID attribute specified.
 
5026
 *
 
5027
 * [ VC: ID Attribute Default ]
 
5028
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
 
5029
 *
 
5030
 * [ VC: IDREF ]
 
5031
 * Values of type IDREF must match the Name production, and values
 
5032
 * of type IDREFS must match Names; each IDREF Name must match the value
 
5033
 * of an ID attribute on some element in the XML document; i.e. IDREF
 
5034
 * values must match the value of some ID attribute.
 
5035
 *
 
5036
 * [ VC: Entity Name ]
 
5037
 * Values of type ENTITY must match the Name production, values
 
5038
 * of type ENTITIES must match Names; each Entity Name must match the
 
5039
 * name of an unparsed entity declared in the DTD.  
 
5040
 *
 
5041
 * [ VC: Name Token ]
 
5042
 * Values of type NMTOKEN must match the Nmtoken production; values
 
5043
 * of type NMTOKENS must match Nmtokens. 
 
5044
 *
 
5045
 * Returns the attribute type
 
5046
 */
 
5047
int 
 
5048
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
 
5049
    SHRINK;
 
5050
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
 
5051
        SKIP(5);
 
5052
        return(XML_ATTRIBUTE_CDATA);
 
5053
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
 
5054
        SKIP(6);
 
5055
        return(XML_ATTRIBUTE_IDREFS);
 
5056
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
 
5057
        SKIP(5);
 
5058
        return(XML_ATTRIBUTE_IDREF);
 
5059
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
 
5060
        SKIP(2);
 
5061
        return(XML_ATTRIBUTE_ID);
 
5062
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
 
5063
        SKIP(6);
 
5064
        return(XML_ATTRIBUTE_ENTITY);
 
5065
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
 
5066
        SKIP(8);
 
5067
        return(XML_ATTRIBUTE_ENTITIES);
 
5068
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
 
5069
        SKIP(8);
 
5070
        return(XML_ATTRIBUTE_NMTOKENS);
 
5071
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
 
5072
        SKIP(7);
 
5073
        return(XML_ATTRIBUTE_NMTOKEN);
 
5074
     }
 
5075
     return(xmlParseEnumeratedType(ctxt, tree));
 
5076
}
 
5077
 
 
5078
/**
 
5079
 * xmlParseAttributeListDecl:
 
5080
 * @ctxt:  an XML parser context
 
5081
 *
 
5082
 * : parse the Attribute list def for an element
 
5083
 *
 
5084
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
 
5085
 *
 
5086
 * [53] AttDef ::= S Name S AttType S DefaultDecl
 
5087
 *
 
5088
 */
 
5089
void
 
5090
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 
5091
    const xmlChar *elemName;
 
5092
    const xmlChar *attrName;
 
5093
    xmlEnumerationPtr tree;
 
5094
 
 
5095
    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
 
5096
        xmlParserInputPtr input = ctxt->input;
 
5097
 
 
5098
        SKIP(9);
 
5099
        if (!IS_BLANK_CH(CUR)) {
 
5100
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5101
                                 "Space required after '<!ATTLIST'\n");
 
5102
        }
 
5103
        SKIP_BLANKS;
 
5104
        elemName = xmlParseName(ctxt);
 
5105
        if (elemName == NULL) {
 
5106
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5107
                           "ATTLIST: no name for Element\n");
 
5108
            return;
 
5109
        }
 
5110
        SKIP_BLANKS;
 
5111
        GROW;
 
5112
        while (RAW != '>') {
 
5113
            const xmlChar *check = CUR_PTR;
 
5114
            int type;
 
5115
            int def;
 
5116
            xmlChar *defaultValue = NULL;
 
5117
 
 
5118
            GROW;
 
5119
            tree = NULL;
 
5120
            attrName = xmlParseName(ctxt);
 
5121
            if (attrName == NULL) {
 
5122
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5123
                               "ATTLIST: no name for Attribute\n");
 
5124
                break;
 
5125
            }
 
5126
            GROW;
 
5127
            if (!IS_BLANK_CH(CUR)) {
 
5128
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5129
                        "Space required after the attribute name\n");
 
5130
                break;
 
5131
            }
 
5132
            SKIP_BLANKS;
 
5133
 
 
5134
            type = xmlParseAttributeType(ctxt, &tree);
 
5135
            if (type <= 0) {
 
5136
                break;
 
5137
            }
 
5138
 
 
5139
            GROW;
 
5140
            if (!IS_BLANK_CH(CUR)) {
 
5141
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5142
                               "Space required after the attribute type\n");
 
5143
                if (tree != NULL)
 
5144
                    xmlFreeEnumeration(tree);
 
5145
                break;
 
5146
            }
 
5147
            SKIP_BLANKS;
 
5148
 
 
5149
            def = xmlParseDefaultDecl(ctxt, &defaultValue);
 
5150
            if (def <= 0) {
 
5151
                if (defaultValue != NULL)
 
5152
                    xmlFree(defaultValue);
 
5153
                if (tree != NULL)
 
5154
                    xmlFreeEnumeration(tree);
 
5155
                break;
 
5156
            }
 
5157
            if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
 
5158
                xmlAttrNormalizeSpace(defaultValue, defaultValue);
 
5159
 
 
5160
            GROW;
 
5161
            if (RAW != '>') {
 
5162
                if (!IS_BLANK_CH(CUR)) {
 
5163
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5164
                        "Space required after the attribute default value\n");
 
5165
                    if (defaultValue != NULL)
 
5166
                        xmlFree(defaultValue);
 
5167
                    if (tree != NULL)
 
5168
                        xmlFreeEnumeration(tree);
 
5169
                    break;
 
5170
                }
 
5171
                SKIP_BLANKS;
 
5172
            }
 
5173
            if (check == CUR_PTR) {
 
5174
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
5175
                            "in xmlParseAttributeListDecl\n");
 
5176
                if (defaultValue != NULL)
 
5177
                    xmlFree(defaultValue);
 
5178
                if (tree != NULL)
 
5179
                    xmlFreeEnumeration(tree);
 
5180
                break;
 
5181
            }
 
5182
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
5183
                (ctxt->sax->attributeDecl != NULL))
 
5184
                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
 
5185
                                type, def, defaultValue, tree);
 
5186
            else if (tree != NULL)
 
5187
                xmlFreeEnumeration(tree);
 
5188
 
 
5189
            if ((ctxt->sax2) && (defaultValue != NULL) &&
 
5190
                (def != XML_ATTRIBUTE_IMPLIED) && 
 
5191
                (def != XML_ATTRIBUTE_REQUIRED)) {
 
5192
                xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
 
5193
            }
 
5194
            if (ctxt->sax2) {
 
5195
                xmlAddSpecialAttr(ctxt, elemName, attrName, type);
 
5196
            }
 
5197
            if (defaultValue != NULL)
 
5198
                xmlFree(defaultValue);
 
5199
            GROW;
 
5200
        }
 
5201
        if (RAW == '>') {
 
5202
            if (input != ctxt->input) {
 
5203
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5204
    "Attribute list declaration doesn't start and stop in the same entity\n");
 
5205
            }
 
5206
            NEXT;
 
5207
        }
 
5208
    }
 
5209
}
 
5210
 
 
5211
/**
 
5212
 * xmlParseElementMixedContentDecl:
 
5213
 * @ctxt:  an XML parser context
 
5214
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
5215
 *
 
5216
 * parse the declaration for a Mixed Element content
 
5217
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
5218
 * 
 
5219
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
 
5220
 *                '(' S? '#PCDATA' S? ')'
 
5221
 *
 
5222
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
 
5223
 *
 
5224
 * [ VC: No Duplicate Types ]
 
5225
 * The same name must not appear more than once in a single
 
5226
 * mixed-content declaration. 
 
5227
 *
 
5228
 * returns: the list of the xmlElementContentPtr describing the element choices
 
5229
 */
 
5230
xmlElementContentPtr
 
5231
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 
5232
    xmlElementContentPtr ret = NULL, cur = NULL, n;
 
5233
    const xmlChar *elem = NULL;
 
5234
 
 
5235
    GROW;
 
5236
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 
5237
        SKIP(7);
 
5238
        SKIP_BLANKS;
 
5239
        SHRINK;
 
5240
        if (RAW == ')') {
 
5241
            if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
5242
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5243
"Element content declaration doesn't start and stop in the same entity\n",
 
5244
                                 NULL);
 
5245
            }
 
5246
            NEXT;
 
5247
            ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 
5248
            if (ret == NULL)
 
5249
                return(NULL);
 
5250
            if (RAW == '*') {
 
5251
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
5252
                NEXT;
 
5253
            }
 
5254
            return(ret);
 
5255
        }
 
5256
        if ((RAW == '(') || (RAW == '|')) {
 
5257
            ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 
5258
            if (ret == NULL) return(NULL);
 
5259
        }
 
5260
        while (RAW == '|') {
 
5261
            NEXT;
 
5262
            if (elem == NULL) {
 
5263
                ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
5264
                if (ret == NULL) return(NULL);
 
5265
                ret->c1 = cur;
 
5266
                if (cur != NULL)
 
5267
                    cur->parent = ret;
 
5268
                cur = ret;
 
5269
            } else {
 
5270
                n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
5271
                if (n == NULL) return(NULL);
 
5272
                n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
5273
                if (n->c1 != NULL)
 
5274
                    n->c1->parent = n;
 
5275
                cur->c2 = n;
 
5276
                if (n != NULL)
 
5277
                    n->parent = cur;
 
5278
                cur = n;
 
5279
            }
 
5280
            SKIP_BLANKS;
 
5281
            elem = xmlParseName(ctxt);
 
5282
            if (elem == NULL) {
 
5283
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5284
                        "xmlParseElementMixedContentDecl : Name expected\n");
 
5285
                xmlFreeDocElementContent(ctxt->myDoc, cur);
 
5286
                return(NULL);
 
5287
            }
 
5288
            SKIP_BLANKS;
 
5289
            GROW;
 
5290
        }
 
5291
        if ((RAW == ')') && (NXT(1) == '*')) {
 
5292
            if (elem != NULL) {
 
5293
                cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
 
5294
                                               XML_ELEMENT_CONTENT_ELEMENT);
 
5295
                if (cur->c2 != NULL)
 
5296
                    cur->c2->parent = cur;
 
5297
            }
 
5298
            ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
5299
            if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
5300
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5301
"Element content declaration doesn't start and stop in the same entity\n",
 
5302
                                 NULL);
 
5303
            }
 
5304
            SKIP(2);
 
5305
        } else {
 
5306
            xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5307
            xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
 
5308
            return(NULL);
 
5309
        }
 
5310
 
 
5311
    } else {
 
5312
        xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
 
5313
    }
 
5314
    return(ret);
 
5315
}
 
5316
 
 
5317
/**
 
5318
 * xmlParseElementChildrenContentDecl:
 
5319
 * @ctxt:  an XML parser context
 
5320
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
5321
 *
 
5322
 * parse the declaration for a Mixed Element content
 
5323
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
5324
 * 
 
5325
 *
 
5326
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
 
5327
 *
 
5328
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
 
5329
 *
 
5330
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
 
5331
 *
 
5332
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
 
5333
 *
 
5334
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
 
5335
 * TODO Parameter-entity replacement text must be properly nested
 
5336
 *      with parenthesized groups. That is to say, if either of the
 
5337
 *      opening or closing parentheses in a choice, seq, or Mixed
 
5338
 *      construct is contained in the replacement text for a parameter
 
5339
 *      entity, both must be contained in the same replacement text. For
 
5340
 *      interoperability, if a parameter-entity reference appears in a
 
5341
 *      choice, seq, or Mixed construct, its replacement text should not
 
5342
 *      be empty, and neither the first nor last non-blank character of
 
5343
 *      the replacement text should be a connector (| or ,).
 
5344
 *
 
5345
 * Returns the tree of xmlElementContentPtr describing the element 
 
5346
 *          hierarchy.
 
5347
 */
 
5348
xmlElementContentPtr
 
5349
xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk) {
 
5350
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
 
5351
    const xmlChar *elem;
 
5352
    xmlChar type = 0;
 
5353
 
 
5354
    SKIP_BLANKS;
 
5355
    GROW;
 
5356
    if (RAW == '(') {
 
5357
        int inputid = ctxt->input->id;
 
5358
 
 
5359
        /* Recurse on first child */
 
5360
        NEXT;
 
5361
        SKIP_BLANKS;
 
5362
        cur = ret = xmlParseElementChildrenContentDecl(ctxt, inputid);
 
5363
        SKIP_BLANKS;
 
5364
        GROW;
 
5365
    } else {
 
5366
        elem = xmlParseName(ctxt);
 
5367
        if (elem == NULL) {
 
5368
            xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
 
5369
            return(NULL);
 
5370
        }
 
5371
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
5372
        if (cur == NULL) {
 
5373
            xmlErrMemory(ctxt, NULL);
 
5374
            return(NULL);
 
5375
        }
 
5376
        GROW;
 
5377
        if (RAW == '?') {
 
5378
            cur->ocur = XML_ELEMENT_CONTENT_OPT;
 
5379
            NEXT;
 
5380
        } else if (RAW == '*') {
 
5381
            cur->ocur = XML_ELEMENT_CONTENT_MULT;
 
5382
            NEXT;
 
5383
        } else if (RAW == '+') {
 
5384
            cur->ocur = XML_ELEMENT_CONTENT_PLUS;
 
5385
            NEXT;
 
5386
        } else {
 
5387
            cur->ocur = XML_ELEMENT_CONTENT_ONCE;
 
5388
        }
 
5389
        GROW;
 
5390
    }
 
5391
    SKIP_BLANKS;
 
5392
    SHRINK;
 
5393
    while (RAW != ')') {
 
5394
        /*
 
5395
         * Each loop we parse one separator and one element.
 
5396
         */
 
5397
        if (RAW == ',') {
 
5398
            if (type == 0) type = CUR;
 
5399
 
 
5400
            /*
 
5401
             * Detect "Name | Name , Name" error
 
5402
             */
 
5403
            else if (type != CUR) {
 
5404
                xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
 
5405
                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
 
5406
                                  type);
 
5407
                if ((last != NULL) && (last != ret))
 
5408
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
5409
                if (ret != NULL)
 
5410
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5411
                return(NULL);
 
5412
            }
 
5413
            NEXT;
 
5414
 
 
5415
            op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
 
5416
            if (op == NULL) {
 
5417
                if ((last != NULL) && (last != ret))
 
5418
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
5419
                xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5420
                return(NULL);
 
5421
            }
 
5422
            if (last == NULL) {
 
5423
                op->c1 = ret;
 
5424
                if (ret != NULL)
 
5425
                    ret->parent = op;
 
5426
                ret = cur = op;
 
5427
            } else {
 
5428
                cur->c2 = op;
 
5429
                if (op != NULL)
 
5430
                    op->parent = cur;
 
5431
                op->c1 = last;
 
5432
                if (last != NULL)
 
5433
                    last->parent = op;
 
5434
                cur =op;
 
5435
                last = NULL;
 
5436
            }
 
5437
        } else if (RAW == '|') {
 
5438
            if (type == 0) type = CUR;
 
5439
 
 
5440
            /*
 
5441
             * Detect "Name , Name | Name" error
 
5442
             */
 
5443
            else if (type != CUR) {
 
5444
                xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
 
5445
                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
 
5446
                                  type);
 
5447
                if ((last != NULL) && (last != ret))
 
5448
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
5449
                if (ret != NULL)
 
5450
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5451
                return(NULL);
 
5452
            }
 
5453
            NEXT;
 
5454
 
 
5455
            op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
5456
            if (op == NULL) {
 
5457
                if ((last != NULL) && (last != ret))
 
5458
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
5459
                if (ret != NULL)
 
5460
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5461
                return(NULL);
 
5462
            }
 
5463
            if (last == NULL) {
 
5464
                op->c1 = ret;
 
5465
                if (ret != NULL)
 
5466
                    ret->parent = op;
 
5467
                ret = cur = op;
 
5468
            } else {
 
5469
                cur->c2 = op;
 
5470
                if (op != NULL)
 
5471
                    op->parent = cur;
 
5472
                op->c1 = last;
 
5473
                if (last != NULL)
 
5474
                    last->parent = op;
 
5475
                cur =op;
 
5476
                last = NULL;
 
5477
            }
 
5478
        } else {
 
5479
            xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
 
5480
            if ((last != NULL) && (last != ret))
 
5481
                xmlFreeDocElementContent(ctxt->myDoc, last);
 
5482
            if (ret != NULL)
 
5483
                xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5484
            return(NULL);
 
5485
        }
 
5486
        GROW;
 
5487
        SKIP_BLANKS;
 
5488
        GROW;
 
5489
        if (RAW == '(') {
 
5490
            int inputid = ctxt->input->id;
 
5491
            /* Recurse on second child */
 
5492
            NEXT;
 
5493
            SKIP_BLANKS;
 
5494
            last = xmlParseElementChildrenContentDecl(ctxt, inputid);
 
5495
            SKIP_BLANKS;
 
5496
        } else {
 
5497
            elem = xmlParseName(ctxt);
 
5498
            if (elem == NULL) {
 
5499
                xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
 
5500
                if (ret != NULL)
 
5501
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5502
                return(NULL);
 
5503
            }
 
5504
            last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
5505
            if (last == NULL) {
 
5506
                if (ret != NULL)
 
5507
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
5508
                return(NULL);
 
5509
            }
 
5510
            if (RAW == '?') {
 
5511
                last->ocur = XML_ELEMENT_CONTENT_OPT;
 
5512
                NEXT;
 
5513
            } else if (RAW == '*') {
 
5514
                last->ocur = XML_ELEMENT_CONTENT_MULT;
 
5515
                NEXT;
 
5516
            } else if (RAW == '+') {
 
5517
                last->ocur = XML_ELEMENT_CONTENT_PLUS;
 
5518
                NEXT;
 
5519
            } else {
 
5520
                last->ocur = XML_ELEMENT_CONTENT_ONCE;
 
5521
            }
 
5522
        }
 
5523
        SKIP_BLANKS;
 
5524
        GROW;
 
5525
    }
 
5526
    if ((cur != NULL) && (last != NULL)) {
 
5527
        cur->c2 = last;
 
5528
        if (last != NULL)
 
5529
            last->parent = cur;
 
5530
    }
 
5531
    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
5532
        xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5533
"Element content declaration doesn't start and stop in the same entity\n",
 
5534
                         NULL);
 
5535
    }
 
5536
    NEXT;
 
5537
    if (RAW == '?') {
 
5538
        if (ret != NULL) {
 
5539
            if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
 
5540
                (ret->ocur == XML_ELEMENT_CONTENT_MULT))
 
5541
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
5542
            else
 
5543
                ret->ocur = XML_ELEMENT_CONTENT_OPT;
 
5544
        }
 
5545
        NEXT;
 
5546
    } else if (RAW == '*') {
 
5547
        if (ret != NULL) {
 
5548
            ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
5549
            cur = ret;
 
5550
            /*
 
5551
             * Some normalization:
 
5552
             * (a | b* | c?)* == (a | b | c)*
 
5553
             */
 
5554
            while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
 
5555
                if ((cur->c1 != NULL) &&
 
5556
                    ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
5557
                     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
 
5558
                    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
 
5559
                if ((cur->c2 != NULL) &&
 
5560
                    ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
5561
                     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
 
5562
                    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
 
5563
                cur = cur->c2;
 
5564
            }
 
5565
        }
 
5566
        NEXT;
 
5567
    } else if (RAW == '+') {
 
5568
        if (ret != NULL) {
 
5569
            int found = 0;
 
5570
 
 
5571
            if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
5572
                (ret->ocur == XML_ELEMENT_CONTENT_MULT))
 
5573
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
5574
            else
 
5575
                ret->ocur = XML_ELEMENT_CONTENT_PLUS;
 
5576
            /*
 
5577
             * Some normalization:
 
5578
             * (a | b*)+ == (a | b)*
 
5579
             * (a | b?)+ == (a | b)*
 
5580
             */
 
5581
            while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
 
5582
                if ((cur->c1 != NULL) &&
 
5583
                    ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
5584
                     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
 
5585
                    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
 
5586
                    found = 1;
 
5587
                }
 
5588
                if ((cur->c2 != NULL) &&
 
5589
                    ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
5590
                     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
 
5591
                    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
 
5592
                    found = 1;
 
5593
                }
 
5594
                cur = cur->c2;
 
5595
            }
 
5596
            if (found)
 
5597
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
5598
        }
 
5599
        NEXT;
 
5600
    }
 
5601
    return(ret);
 
5602
}
 
5603
 
 
5604
/**
 
5605
 * xmlParseElementContentDecl:
 
5606
 * @ctxt:  an XML parser context
 
5607
 * @name:  the name of the element being defined.
 
5608
 * @result:  the Element Content pointer will be stored here if any
 
5609
 *
 
5610
 * parse the declaration for an Element content either Mixed or Children,
 
5611
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
 
5612
 * 
 
5613
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
 
5614
 *
 
5615
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
 
5616
 */
 
5617
 
 
5618
int
 
5619
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
 
5620
                           xmlElementContentPtr *result) {
 
5621
 
 
5622
    xmlElementContentPtr tree = NULL;
 
5623
    int inputid = ctxt->input->id;
 
5624
    int res;
 
5625
 
 
5626
    *result = NULL;
 
5627
 
 
5628
    if (RAW != '(') {
 
5629
        xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
 
5630
                "xmlParseElementContentDecl : %s '(' expected\n", name);
 
5631
        return(-1);
 
5632
    }
 
5633
    NEXT;
 
5634
    GROW;
 
5635
    SKIP_BLANKS;
 
5636
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 
5637
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
 
5638
        res = XML_ELEMENT_TYPE_MIXED;
 
5639
    } else {
 
5640
        tree = xmlParseElementChildrenContentDecl(ctxt, inputid);
 
5641
        res = XML_ELEMENT_TYPE_ELEMENT;
 
5642
    }
 
5643
    SKIP_BLANKS;
 
5644
    *result = tree;
 
5645
    return(res);
 
5646
}
 
5647
 
 
5648
/**
 
5649
 * xmlParseElementDecl:
 
5650
 * @ctxt:  an XML parser context
 
5651
 *
 
5652
 * parse an Element declaration.
 
5653
 *
 
5654
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
 
5655
 *
 
5656
 * [ VC: Unique Element Type Declaration ]
 
5657
 * No element type may be declared more than once
 
5658
 *
 
5659
 * Returns the type of the element, or -1 in case of error
 
5660
 */
 
5661
int
 
5662
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
 
5663
    const xmlChar *name;
 
5664
    int ret = -1;
 
5665
    xmlElementContentPtr content  = NULL;
 
5666
 
 
5667
    /* GROW; done in the caller */
 
5668
    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
 
5669
        xmlParserInputPtr input = ctxt->input;
 
5670
 
 
5671
        SKIP(9);
 
5672
        if (!IS_BLANK_CH(CUR)) {
 
5673
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5674
                           "Space required after 'ELEMENT'\n");
 
5675
        }
 
5676
        SKIP_BLANKS;
 
5677
        name = xmlParseName(ctxt);
 
5678
        if (name == NULL) {
 
5679
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5680
                           "xmlParseElementDecl: no name for Element\n");
 
5681
            return(-1);
 
5682
        }
 
5683
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
5684
            xmlPopInput(ctxt);
 
5685
        if (!IS_BLANK_CH(CUR)) {
 
5686
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5687
                           "Space required after the element name\n");
 
5688
        }
 
5689
        SKIP_BLANKS;
 
5690
        if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
 
5691
            SKIP(5);
 
5692
            /*
 
5693
             * Element must always be empty.
 
5694
             */
 
5695
            ret = XML_ELEMENT_TYPE_EMPTY;
 
5696
        } else if ((RAW == 'A') && (NXT(1) == 'N') &&
 
5697
                   (NXT(2) == 'Y')) {
 
5698
            SKIP(3);
 
5699
            /*
 
5700
             * Element is a generic container.
 
5701
             */
 
5702
            ret = XML_ELEMENT_TYPE_ANY;
 
5703
        } else if (RAW == '(') {
 
5704
            ret = xmlParseElementContentDecl(ctxt, name, &content);
 
5705
        } else {
 
5706
            /*
 
5707
             * [ WFC: PEs in Internal Subset ] error handling.
 
5708
             */
 
5709
            if ((RAW == '%') && (ctxt->external == 0) &&
 
5710
                (ctxt->inputNr == 1)) {
 
5711
                xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
 
5712
          "PEReference: forbidden within markup decl in internal subset\n");
 
5713
            } else {
 
5714
                xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
 
5715
                      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
 
5716
            }
 
5717
            return(-1);
 
5718
        }
 
5719
 
 
5720
        SKIP_BLANKS;
 
5721
        /*
 
5722
         * Pop-up of finished entities.
 
5723
         */
 
5724
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
5725
            xmlPopInput(ctxt);
 
5726
        SKIP_BLANKS;
 
5727
 
 
5728
        if (RAW != '>') {
 
5729
            xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
5730
            if (content != NULL) {
 
5731
                xmlFreeDocElementContent(ctxt->myDoc, content);
 
5732
            }
 
5733
        } else {
 
5734
            if (input != ctxt->input) {
 
5735
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5736
    "Element declaration doesn't start and stop in the same entity\n");
 
5737
            }
 
5738
                
 
5739
            NEXT;
 
5740
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
5741
                (ctxt->sax->elementDecl != NULL)) {
 
5742
                if (content != NULL)
 
5743
                    content->parent = NULL;
 
5744
                ctxt->sax->elementDecl(ctxt->userData, name, ret,
 
5745
                                       content);
 
5746
                if ((content != NULL) && (content->parent == NULL)) {
 
5747
                    /*
 
5748
                     * this is a trick: if xmlAddElementDecl is called,
 
5749
                     * instead of copying the full tree it is plugged directly
 
5750
                     * if called from the parser. Avoid duplicating the 
 
5751
                     * interfaces or change the API/ABI
 
5752
                     */
 
5753
                    xmlFreeDocElementContent(ctxt->myDoc, content);
 
5754
                }
 
5755
            } else if (content != NULL) {
 
5756
                xmlFreeDocElementContent(ctxt->myDoc, content);
 
5757
            }
 
5758
        }
 
5759
    }
 
5760
    return(ret);
 
5761
}
 
5762
 
 
5763
/**
 
5764
 * xmlParseConditionalSections
 
5765
 * @ctxt:  an XML parser context
 
5766
 *
 
5767
 * [61] conditionalSect ::= includeSect | ignoreSect 
 
5768
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' 
 
5769
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
 
5770
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
 
5771
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
 
5772
 */
 
5773
 
 
5774
static void
 
5775
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
5776
    SKIP(3);
 
5777
    SKIP_BLANKS;
 
5778
    if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
 
5779
        SKIP(7);
 
5780
        SKIP_BLANKS;
 
5781
        if (RAW != '[') {
 
5782
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
 
5783
        } else {
 
5784
            NEXT;
 
5785
        }
 
5786
        if (xmlParserDebugEntities) {
 
5787
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
5788
                xmlGenericError(xmlGenericErrorContext,
 
5789
                        "%s(%d): ", ctxt->input->filename,
 
5790
                        ctxt->input->line);
 
5791
            xmlGenericError(xmlGenericErrorContext,
 
5792
                    "Entering INCLUDE Conditional Section\n");
 
5793
        }
 
5794
 
 
5795
        while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
 
5796
               (NXT(2) != '>'))) {
 
5797
            const xmlChar *check = CUR_PTR;
 
5798
            unsigned int cons = ctxt->input->consumed;
 
5799
 
 
5800
            if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
5801
                xmlParseConditionalSections(ctxt);
 
5802
            } else if (IS_BLANK_CH(CUR)) {
 
5803
                NEXT;
 
5804
            } else if (RAW == '%') {
 
5805
                xmlParsePEReference(ctxt);
 
5806
            } else
 
5807
                xmlParseMarkupDecl(ctxt);
 
5808
 
 
5809
            /*
 
5810
             * Pop-up of finished entities.
 
5811
             */
 
5812
            while ((RAW == 0) && (ctxt->inputNr > 1))
 
5813
                xmlPopInput(ctxt);
 
5814
 
 
5815
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
5816
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
5817
                break;
 
5818
            }
 
5819
        }
 
5820
        if (xmlParserDebugEntities) {
 
5821
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
5822
                xmlGenericError(xmlGenericErrorContext,
 
5823
                        "%s(%d): ", ctxt->input->filename,
 
5824
                        ctxt->input->line);
 
5825
            xmlGenericError(xmlGenericErrorContext,
 
5826
                    "Leaving INCLUDE Conditional Section\n");
 
5827
        }
 
5828
 
 
5829
    } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
 
5830
        int state;
 
5831
        xmlParserInputState instate;
 
5832
        int depth = 0;
 
5833
 
 
5834
        SKIP(6);
 
5835
        SKIP_BLANKS;
 
5836
        if (RAW != '[') {
 
5837
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
 
5838
        } else {
 
5839
            NEXT;
 
5840
        }
 
5841
        if (xmlParserDebugEntities) {
 
5842
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
5843
                xmlGenericError(xmlGenericErrorContext,
 
5844
                        "%s(%d): ", ctxt->input->filename,
 
5845
                        ctxt->input->line);
 
5846
            xmlGenericError(xmlGenericErrorContext,
 
5847
                    "Entering IGNORE Conditional Section\n");
 
5848
        }
 
5849
 
 
5850
        /*
 
5851
         * Parse up to the end of the conditional section
 
5852
         * But disable SAX event generating DTD building in the meantime
 
5853
         */
 
5854
        state = ctxt->disableSAX;
 
5855
        instate = ctxt->instate;
 
5856
        if (ctxt->recovery == 0) ctxt->disableSAX = 1;
 
5857
        ctxt->instate = XML_PARSER_IGNORE;
 
5858
 
 
5859
        while ((depth >= 0) && (RAW != 0)) {
 
5860
          if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
5861
            depth++;
 
5862
            SKIP(3);
 
5863
            continue;
 
5864
          }
 
5865
          if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
 
5866
            if (--depth >= 0) SKIP(3);
 
5867
            continue;
 
5868
          }
 
5869
          NEXT;
 
5870
          continue;
 
5871
        }
 
5872
 
 
5873
        ctxt->disableSAX = state;
 
5874
        ctxt->instate = instate;
 
5875
 
 
5876
        if (xmlParserDebugEntities) {
 
5877
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
5878
                xmlGenericError(xmlGenericErrorContext,
 
5879
                        "%s(%d): ", ctxt->input->filename,
 
5880
                        ctxt->input->line);
 
5881
            xmlGenericError(xmlGenericErrorContext,
 
5882
                    "Leaving IGNORE Conditional Section\n");
 
5883
        }
 
5884
 
 
5885
    } else {
 
5886
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
 
5887
    }
 
5888
 
 
5889
    if (RAW == 0)
 
5890
        SHRINK;
 
5891
 
 
5892
    if (RAW == 0) {
 
5893
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
 
5894
    } else {
 
5895
        SKIP(3);
 
5896
    }
 
5897
}
 
5898
 
 
5899
/**
 
5900
 * xmlParseMarkupDecl:
 
5901
 * @ctxt:  an XML parser context
 
5902
 * 
 
5903
 * parse Markup declarations
 
5904
 *
 
5905
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
 
5906
 *                     NotationDecl | PI | Comment
 
5907
 *
 
5908
 * [ VC: Proper Declaration/PE Nesting ]
 
5909
 * Parameter-entity replacement text must be properly nested with
 
5910
 * markup declarations. That is to say, if either the first character
 
5911
 * or the last character of a markup declaration (markupdecl above) is
 
5912
 * contained in the replacement text for a parameter-entity reference,
 
5913
 * both must be contained in the same replacement text.
 
5914
 *
 
5915
 * [ WFC: PEs in Internal Subset ]
 
5916
 * In the internal DTD subset, parameter-entity references can occur
 
5917
 * only where markup declarations can occur, not within markup declarations.
 
5918
 * (This does not apply to references that occur in external parameter
 
5919
 * entities or to the external subset.) 
 
5920
 */
 
5921
void
 
5922
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
 
5923
    GROW;
 
5924
    if (CUR == '<') {
 
5925
        if (NXT(1) == '!') {
 
5926
            switch (NXT(2)) {
 
5927
                case 'E':
 
5928
                    if (NXT(3) == 'L')
 
5929
                        xmlParseElementDecl(ctxt);
 
5930
                    else if (NXT(3) == 'N')
 
5931
                        xmlParseEntityDecl(ctxt);
 
5932
                    break;
 
5933
                case 'A':
 
5934
                    xmlParseAttributeListDecl(ctxt);
 
5935
                    break;
 
5936
                case 'N':
 
5937
                    xmlParseNotationDecl(ctxt);
 
5938
                    break;
 
5939
                case '-':
 
5940
                    xmlParseComment(ctxt);
 
5941
                    break;
 
5942
                default:
 
5943
                    /* there is an error but it will be detected later */
 
5944
                    break;
 
5945
            }
 
5946
        } else if (NXT(1) == '?') {
 
5947
            xmlParsePI(ctxt);
 
5948
        }
 
5949
    }
 
5950
    /*
 
5951
     * This is only for internal subset. On external entities,
 
5952
     * the replacement is done before parsing stage
 
5953
     */
 
5954
    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
 
5955
        xmlParsePEReference(ctxt);
 
5956
 
 
5957
    /*
 
5958
     * Conditional sections are allowed from entities included
 
5959
     * by PE References in the internal subset.
 
5960
     */
 
5961
    if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
 
5962
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
5963
            xmlParseConditionalSections(ctxt);
 
5964
        }
 
5965
    }
 
5966
 
 
5967
    ctxt->instate = XML_PARSER_DTD;
 
5968
}
 
5969
 
 
5970
/**
 
5971
 * xmlParseTextDecl:
 
5972
 * @ctxt:  an XML parser context
 
5973
 * 
 
5974
 * parse an XML declaration header for external entities
 
5975
 *
 
5976
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
 
5977
 *
 
5978
 * Question: Seems that EncodingDecl is mandatory ? Is that a typo ?
 
5979
 */
 
5980
 
 
5981
void
 
5982
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
 
5983
    xmlChar *version;
 
5984
    const xmlChar *encoding;
 
5985
 
 
5986
    /*
 
5987
     * We know that '<?xml' is here.
 
5988
     */
 
5989
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
5990
        SKIP(5);
 
5991
    } else {
 
5992
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
 
5993
        return;
 
5994
    }
 
5995
 
 
5996
    if (!IS_BLANK_CH(CUR)) {
 
5997
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5998
                       "Space needed after '<?xml'\n");
 
5999
    }
 
6000
    SKIP_BLANKS;
 
6001
 
 
6002
    /*
 
6003
     * We may have the VersionInfo here.
 
6004
     */
 
6005
    version = xmlParseVersionInfo(ctxt);
 
6006
    if (version == NULL)
 
6007
        version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
6008
    else {
 
6009
        if (!IS_BLANK_CH(CUR)) {
 
6010
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6011
                           "Space needed here\n");
 
6012
        }
 
6013
    }
 
6014
    ctxt->input->version = version;
 
6015
 
 
6016
    /*
 
6017
     * We must have the encoding declaration
 
6018
     */
 
6019
    encoding = xmlParseEncodingDecl(ctxt);
 
6020
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
6021
        /*
 
6022
         * The XML REC instructs us to stop parsing right here
 
6023
         */
 
6024
        return;
 
6025
    }
 
6026
    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
 
6027
        xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
 
6028
                       "Missing encoding in text declaration\n");
 
6029
    }
 
6030
 
 
6031
    SKIP_BLANKS;
 
6032
    if ((RAW == '?') && (NXT(1) == '>')) {
 
6033
        SKIP(2);
 
6034
    } else if (RAW == '>') {
 
6035
        /* Deprecated old WD ... */
 
6036
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
6037
        NEXT;
 
6038
    } else {
 
6039
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
6040
        MOVETO_ENDTAG(CUR_PTR);
 
6041
        NEXT;
 
6042
    }
 
6043
}
 
6044
 
 
6045
/**
 
6046
 * xmlParseExternalSubset:
 
6047
 * @ctxt:  an XML parser context
 
6048
 * @ExternalID: the external identifier
 
6049
 * @SystemID: the system identifier (or URL)
 
6050
 * 
 
6051
 * parse Markup declarations from an external subset
 
6052
 *
 
6053
 * [30] extSubset ::= textDecl? extSubsetDecl
 
6054
 *
 
6055
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
 
6056
 */
 
6057
void
 
6058
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
 
6059
                       const xmlChar *SystemID) {
 
6060
    xmlDetectSAX2(ctxt);
 
6061
    GROW;
 
6062
 
 
6063
    if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) &&
 
6064
        (ctxt->input->end - ctxt->input->cur >= 4)) {
 
6065
        xmlChar start[4];
 
6066
        xmlCharEncoding enc;
 
6067
 
 
6068
        start[0] = RAW;
 
6069
        start[1] = NXT(1);
 
6070
        start[2] = NXT(2);
 
6071
        start[3] = NXT(3);
 
6072
        enc = xmlDetectCharEncoding(start, 4);
 
6073
        if (enc != XML_CHAR_ENCODING_NONE)
 
6074
            xmlSwitchEncoding(ctxt, enc);
 
6075
    }
 
6076
 
 
6077
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
 
6078
        xmlParseTextDecl(ctxt);
 
6079
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
6080
            /*
 
6081
             * The XML REC instructs us to stop parsing right here
 
6082
             */
 
6083
            ctxt->instate = XML_PARSER_EOF;
 
6084
            return;
 
6085
        }
 
6086
    }
 
6087
    if (ctxt->myDoc == NULL) {
 
6088
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
6089
    }
 
6090
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
 
6091
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
 
6092
 
 
6093
    ctxt->instate = XML_PARSER_DTD;
 
6094
    ctxt->external = 1;
 
6095
    while (((RAW == '<') && (NXT(1) == '?')) ||
 
6096
           ((RAW == '<') && (NXT(1) == '!')) ||
 
6097
           (RAW == '%') || IS_BLANK_CH(CUR)) {
 
6098
        const xmlChar *check = CUR_PTR;
 
6099
        unsigned int cons = ctxt->input->consumed;
 
6100
 
 
6101
        GROW;
 
6102
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6103
            xmlParseConditionalSections(ctxt);
 
6104
        } else if (IS_BLANK_CH(CUR)) {
 
6105
            NEXT;
 
6106
        } else if (RAW == '%') {
 
6107
            xmlParsePEReference(ctxt);
 
6108
        } else
 
6109
            xmlParseMarkupDecl(ctxt);
 
6110
 
 
6111
        /*
 
6112
         * Pop-up of finished entities.
 
6113
         */
 
6114
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
6115
            xmlPopInput(ctxt);
 
6116
 
 
6117
        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
6118
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
6119
            break;
 
6120
        }
 
6121
    }
 
6122
    
 
6123
    if (RAW != 0) {
 
6124
        xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
6125
    }
 
6126
 
 
6127
}
 
6128
 
 
6129
/**
 
6130
 * xmlParseReference:
 
6131
 * @ctxt:  an XML parser context
 
6132
 * 
 
6133
 * parse and handle entity references in content, depending on the SAX
 
6134
 * interface, this may end-up in a call to character() if this is a
 
6135
 * CharRef, a predefined entity, if there is no reference() callback.
 
6136
 * or if the parser was asked to switch to that mode.
 
6137
 *
 
6138
 * [67] Reference ::= EntityRef | CharRef
 
6139
 */
 
6140
void
 
6141
xmlParseReference(xmlParserCtxtPtr ctxt) {
 
6142
    xmlEntityPtr ent;
 
6143
    xmlChar *val;
 
6144
    if (RAW != '&') return;
 
6145
 
 
6146
    if (NXT(1) == '#') {
 
6147
        int i = 0;
 
6148
        xmlChar out[10];
 
6149
        int hex = NXT(2);
 
6150
        int value = xmlParseCharRef(ctxt);
 
6151
        
 
6152
        if (value == 0)
 
6153
            return;
 
6154
        if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
 
6155
            /*
 
6156
             * So we are using non-UTF-8 buffers
 
6157
             * Check that the char fit on 8bits, if not
 
6158
             * generate a CharRef.
 
6159
             */
 
6160
            if (value <= 0xFF) {
 
6161
                out[0] = value;
 
6162
                out[1] = 0;
 
6163
                if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
6164
                    (!ctxt->disableSAX))
 
6165
                    ctxt->sax->characters(ctxt->userData, out, 1);
 
6166
            } else {
 
6167
                if ((hex == 'x') || (hex == 'X'))
 
6168
                    snprintf((char *)out, sizeof(out), "#x%X", value);
 
6169
                else
 
6170
                    snprintf((char *)out, sizeof(out), "#%d", value);
 
6171
                if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
6172
                    (!ctxt->disableSAX))
 
6173
                    ctxt->sax->reference(ctxt->userData, out);
 
6174
            }
 
6175
        } else {
 
6176
            /*
 
6177
             * Just encode the value in UTF-8
 
6178
             */
 
6179
            COPY_BUF(0 ,out, i, value);
 
6180
            out[i] = 0;
 
6181
            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
6182
                (!ctxt->disableSAX))
 
6183
                ctxt->sax->characters(ctxt->userData, out, i);
 
6184
        }
 
6185
    } else {
 
6186
        int was_checked;
 
6187
 
 
6188
        ent = xmlParseEntityRef(ctxt);
 
6189
        if (ent == NULL) return;
 
6190
        if (!ctxt->wellFormed)
 
6191
            return;
 
6192
        was_checked = ent->checked;
 
6193
        if ((ent->name != NULL) && 
 
6194
            (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
 
6195
            xmlNodePtr list = NULL;
 
6196
            xmlParserErrors ret = XML_ERR_OK;
 
6197
 
 
6198
 
 
6199
            /*
 
6200
             * The first reference to the entity trigger a parsing phase
 
6201
             * where the ent->children is filled with the result from
 
6202
             * the parsing.
 
6203
             */
 
6204
            if (ent->checked == 0) {
 
6205
                xmlChar *value;
 
6206
 
 
6207
                value = ent->content;
 
6208
 
 
6209
                /*
 
6210
                 * Check that this entity is well formed
 
6211
                 */
 
6212
                if ((value != NULL) && (value[0] != 0) &&
 
6213
                    (value[1] == 0) && (value[0] == '<') &&
 
6214
                    (xmlStrEqual(ent->name, BAD_CAST "lt"))) {
 
6215
                    /*
 
6216
                     * DONE: get definite answer on this !!!
 
6217
                     * Lots of entity decls are used to declare a single
 
6218
                     * char 
 
6219
                     *    <!ENTITY lt     "<">
 
6220
                     * Which seems to be valid since
 
6221
                     * 2.4: The ampersand character (&) and the left angle
 
6222
                     * bracket (<) may appear in their literal form only
 
6223
                     * when used ... They are also legal within the literal
 
6224
                     * entity value of an internal entity declaration;i
 
6225
                     * see "4.3.2 Well-Formed Parsed Entities". 
 
6226
                     * IMHO 2.4 and 4.3.2 are directly in contradiction.
 
6227
                     * Looking at the OASIS test suite and James Clark 
 
6228
                     * tests, this is broken. However the XML REC uses
 
6229
                     * it. Is the XML REC not well-formed ????
 
6230
                     * This is a hack to avoid this problem
 
6231
                     *
 
6232
                     * ANSWER: since lt gt amp .. are already defined,
 
6233
                     *   this is a redefinition and hence the fact that the
 
6234
                     *   content is not well balanced is not a Wf error, this
 
6235
                     *   is lousy but acceptable.
 
6236
                     */
 
6237
                    list = xmlNewDocText(ctxt->myDoc, value);
 
6238
                    if (list != NULL) {
 
6239
                        if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) &&
 
6240
                            (ent->children == NULL)) {
 
6241
                            ent->children = list;
 
6242
                            ent->last = list;
 
6243
                            ent->owner = 1;
 
6244
                            list->parent = (xmlNodePtr) ent;
 
6245
                        } else {
 
6246
                            xmlFreeNodeList(list);
 
6247
                        }
 
6248
                    } else if (list != NULL) {
 
6249
                        xmlFreeNodeList(list);
 
6250
                    }
 
6251
                } else {
 
6252
                    /*
 
6253
                     * 4.3.2: An internal general parsed entity is well-formed
 
6254
                     * if its replacement text matches the production labeled
 
6255
                     * content.
 
6256
                     */
 
6257
 
 
6258
                    void *user_data;
 
6259
                    /*
 
6260
                     * This is a bit hackish but this seems the best
 
6261
                     * way to make sure both SAX and DOM entity support
 
6262
                     * behaves okay.
 
6263
                     */
 
6264
                    if (ctxt->userData == ctxt)
 
6265
                        user_data = NULL;
 
6266
                    else
 
6267
                        user_data = ctxt->userData;
 
6268
 
 
6269
                    if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
 
6270
                        ctxt->depth++;
 
6271
                        ret = xmlParseBalancedChunkMemoryInternal(ctxt,
 
6272
                                           value, user_data, &list);
 
6273
                        ctxt->depth--;
 
6274
                    } else if (ent->etype ==
 
6275
                               XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
 
6276
                        ctxt->depth++;
 
6277
                        ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
 
6278
                                   ctxt->sax, user_data, ctxt->depth,
 
6279
                                   ent->URI, ent->ExternalID, &list);
 
6280
                        ctxt->depth--;
 
6281
                    } else {
 
6282
                        ret = XML_ERR_ENTITY_PE_INTERNAL;
 
6283
                        xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
 
6284
                                     "invalid entity type found\n", NULL);
 
6285
                    }
 
6286
                    if (ret == XML_ERR_ENTITY_LOOP) {
 
6287
                        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
6288
                        return;
 
6289
                    } else if ((ret == XML_ERR_OK) && (list != NULL)) {
 
6290
                        if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
 
6291
                         (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
 
6292
                            (ent->children == NULL)) {
 
6293
                            ent->children = list;
 
6294
                            if (ctxt->replaceEntities) {
 
6295
                                /*
 
6296
                                 * Prune it directly in the generated document
 
6297
                                 * except for single text nodes.
 
6298
                                 */
 
6299
                                if (((list->type == XML_TEXT_NODE) &&
 
6300
                                     (list->next == NULL)) ||
 
6301
                                    (ctxt->parseMode == XML_PARSE_READER)) {
 
6302
                                    list->parent = (xmlNodePtr) ent;
 
6303
                                    list = NULL;
 
6304
                                    ent->owner = 1;
 
6305
                                } else {
 
6306
                                    ent->owner = 0;
 
6307
                                    while (list != NULL) {
 
6308
                                        list->parent = (xmlNodePtr) ctxt->node;
 
6309
                                        list->doc = ctxt->myDoc;
 
6310
                                        if (list->next == NULL)
 
6311
                                            ent->last = list;
 
6312
                                        list = list->next;
 
6313
                                    }
 
6314
                                    list = ent->children;
 
6315
#ifdef LIBXML_LEGACY_ENABLED
 
6316
                                    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
6317
                                      xmlAddEntityReference(ent, list, NULL);
 
6318
#endif /* LIBXML_LEGACY_ENABLED */
 
6319
                                }
 
6320
                            } else {
 
6321
                                ent->owner = 1;
 
6322
                                while (list != NULL) {
 
6323
                                    list->parent = (xmlNodePtr) ent;
 
6324
                                    if (list->next == NULL)
 
6325
                                        ent->last = list;
 
6326
                                    list = list->next;
 
6327
                                }
 
6328
                            }
 
6329
                        } else {
 
6330
                            xmlFreeNodeList(list);
 
6331
                            list = NULL;
 
6332
                        }
 
6333
                    } else if ((ret != XML_ERR_OK) &&
 
6334
                               (ret != XML_WAR_UNDECLARED_ENTITY)) {
 
6335
                        xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
6336
                                 "Entity '%s' failed to parse\n", ent->name);
 
6337
                    } else if (list != NULL) {
 
6338
                        xmlFreeNodeList(list);
 
6339
                        list = NULL;
 
6340
                    }
 
6341
                }
 
6342
                ent->checked = 1;
 
6343
            }
 
6344
 
 
6345
            if (ent->children == NULL) {
 
6346
                /*
 
6347
                 * Probably running in SAX mode and the callbacks don't
 
6348
                 * build the entity content. So unless we already went
 
6349
                 * though parsing for first checking go though the entity
 
6350
                 * content to generate callbacks associated to the entity
 
6351
                 */
 
6352
                if (was_checked == 1) {
 
6353
                    void *user_data;
 
6354
                    /*
 
6355
                     * This is a bit hackish but this seems the best
 
6356
                     * way to make sure both SAX and DOM entity support
 
6357
                     * behaves okay.
 
6358
                     */
 
6359
                    if (ctxt->userData == ctxt)
 
6360
                        user_data = NULL;
 
6361
                    else
 
6362
                        user_data = ctxt->userData;
 
6363
 
 
6364
                    if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
 
6365
                        ctxt->depth++;
 
6366
                        ret = xmlParseBalancedChunkMemoryInternal(ctxt,
 
6367
                                           ent->content, user_data, NULL);
 
6368
                        ctxt->depth--;
 
6369
                    } else if (ent->etype ==
 
6370
                               XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
 
6371
                        ctxt->depth++;
 
6372
                        ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
 
6373
                                   ctxt->sax, user_data, ctxt->depth,
 
6374
                                   ent->URI, ent->ExternalID, NULL);
 
6375
                        ctxt->depth--;
 
6376
                    } else {
 
6377
                        ret = XML_ERR_ENTITY_PE_INTERNAL;
 
6378
                        xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
 
6379
                                     "invalid entity type found\n", NULL);
 
6380
                    }
 
6381
                    if (ret == XML_ERR_ENTITY_LOOP) {
 
6382
                        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
6383
                        return;
 
6384
                    }
 
6385
                }
 
6386
                if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
6387
                    (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
 
6388
                    /*
 
6389
                     * Entity reference callback comes second, it's somewhat
 
6390
                     * superfluous but a compatibility to historical behaviour
 
6391
                     */
 
6392
                    ctxt->sax->reference(ctxt->userData, ent->name);
 
6393
                }
 
6394
                return;
 
6395
            }
 
6396
            if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
6397
                (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
 
6398
                /*
 
6399
                 * Create a node.
 
6400
                 */
 
6401
                ctxt->sax->reference(ctxt->userData, ent->name);
 
6402
                return;
 
6403
            }
 
6404
            if ((ctxt->replaceEntities) || (ent->children == NULL))  {
 
6405
                /*
 
6406
                 * There is a problem on the handling of _private for entities
 
6407
                 * (bug 155816): Should we copy the content of the field from
 
6408
                 * the entity (possibly overwriting some value set by the user
 
6409
                 * when a copy is created), should we leave it alone, or should
 
6410
                 * we try to take care of different situations?  The problem
 
6411
                 * is exacerbated by the usage of this field by the xmlReader.
 
6412
                 * To fix this bug, we look at _private on the created node
 
6413
                 * and, if it's NULL, we copy in whatever was in the entity.
 
6414
                 * If it's not NULL we leave it alone.  This is somewhat of a
 
6415
                 * hack - maybe we should have further tests to determine
 
6416
                 * what to do.
 
6417
                 */
 
6418
                if ((ctxt->node != NULL) && (ent->children != NULL)) {
 
6419
                    /*
 
6420
                     * Seems we are generating the DOM content, do
 
6421
                     * a simple tree copy for all references except the first
 
6422
                     * In the first occurrence list contains the replacement.
 
6423
                     * progressive == 2 means we are operating on the Reader
 
6424
                     * and since nodes are discarded we must copy all the time.
 
6425
                     */
 
6426
                    if (((list == NULL) && (ent->owner == 0)) ||
 
6427
                        (ctxt->parseMode == XML_PARSE_READER)) {
 
6428
                        xmlNodePtr nw = NULL, cur, firstChild = NULL;
 
6429
 
 
6430
                        /*
 
6431
                         * when operating on a reader, the entities definitions
 
6432
                         * are always owning the entities subtree.
 
6433
                        if (ctxt->parseMode == XML_PARSE_READER)
 
6434
                            ent->owner = 1;
 
6435
                         */
 
6436
 
 
6437
                        cur = ent->children;
 
6438
                        while (cur != NULL) {
 
6439
                            nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
6440
                            if (nw != NULL) {
 
6441
                                if (nw->_private == NULL)
 
6442
                                    nw->_private = cur->_private;
 
6443
                                if (firstChild == NULL){
 
6444
                                    firstChild = nw;
 
6445
                                }
 
6446
                                nw = xmlAddChild(ctxt->node, nw);
 
6447
                            }
 
6448
                            if (cur == ent->last) {
 
6449
                                /*
 
6450
                                 * needed to detect some strange empty
 
6451
                                 * node cases in the reader tests
 
6452
                                 */
 
6453
                                if ((ctxt->parseMode == XML_PARSE_READER) &&
 
6454
                                    (nw != NULL) &&
 
6455
                                    (nw->type == XML_ELEMENT_NODE) &&
 
6456
                                    (nw->children == NULL))
 
6457
                                    nw->extra = 1;
 
6458
 
 
6459
                                break;
 
6460
                            }
 
6461
                            cur = cur->next;
 
6462
                        }
 
6463
#ifdef LIBXML_LEGACY_ENABLED
 
6464
                        if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)                         
 
6465
                          xmlAddEntityReference(ent, firstChild, nw);
 
6466
#endif /* LIBXML_LEGACY_ENABLED */
 
6467
                    } else if (list == NULL) {
 
6468
                        xmlNodePtr nw = NULL, cur, next, last,
 
6469
                                   firstChild = NULL;
 
6470
                        /*
 
6471
                         * Copy the entity child list and make it the new
 
6472
                         * entity child list. The goal is to make sure any
 
6473
                         * ID or REF referenced will be the one from the
 
6474
                         * document content and not the entity copy.
 
6475
                         */
 
6476
                        cur = ent->children;
 
6477
                        ent->children = NULL;
 
6478
                        last = ent->last;
 
6479
                        ent->last = NULL;
 
6480
                        while (cur != NULL) {
 
6481
                            next = cur->next;
 
6482
                            cur->next = NULL;
 
6483
                            cur->parent = NULL;
 
6484
                            nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
6485
                            if (nw != NULL) {
 
6486
                                if (nw->_private == NULL)
 
6487
                                    nw->_private = cur->_private;
 
6488
                                if (firstChild == NULL){
 
6489
                                    firstChild = cur;
 
6490
                                }
 
6491
                                xmlAddChild((xmlNodePtr) ent, nw);
 
6492
                                xmlAddChild(ctxt->node, cur);
 
6493
                            }
 
6494
                            if (cur == last)
 
6495
                                break;
 
6496
                            cur = next;
 
6497
                        }
 
6498
                        ent->owner = 1;
 
6499
#ifdef LIBXML_LEGACY_ENABLED
 
6500
                        if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)                         
 
6501
                          xmlAddEntityReference(ent, firstChild, nw);
 
6502
#endif /* LIBXML_LEGACY_ENABLED */
 
6503
                    } else {
 
6504
                        const xmlChar *nbktext;
 
6505
 
 
6506
                        /*
 
6507
                         * the name change is to avoid coalescing of the
 
6508
                         * node with a possible previous text one which
 
6509
                         * would make ent->children a dangling pointer
 
6510
                         */
 
6511
                        nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
 
6512
                                                -1);
 
6513
                        if (ent->children->type == XML_TEXT_NODE)
 
6514
                            ent->children->name = nbktext;
 
6515
                        if ((ent->last != ent->children) &&
 
6516
                            (ent->last->type == XML_TEXT_NODE))
 
6517
                            ent->last->name = nbktext;
 
6518
                        xmlAddChildList(ctxt->node, ent->children);
 
6519
                    }
 
6520
 
 
6521
                    /*
 
6522
                     * This is to avoid a nasty side effect, see
 
6523
                     * characters() in SAX.c
 
6524
                     */
 
6525
                    ctxt->nodemem = 0;
 
6526
                    ctxt->nodelen = 0;
 
6527
                    return;
 
6528
                }
 
6529
            }
 
6530
        } else {
 
6531
            val = ent->content;
 
6532
            if (val == NULL) return;
 
6533
            /*
 
6534
             * inline the entity.
 
6535
             */
 
6536
            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
6537
                (!ctxt->disableSAX))
 
6538
                ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
 
6539
        }
 
6540
    }
 
6541
}
 
6542
 
 
6543
/**
 
6544
 * xmlParseEntityRef:
 
6545
 * @ctxt:  an XML parser context
 
6546
 *
 
6547
 * parse ENTITY references declarations
 
6548
 *
 
6549
 * [68] EntityRef ::= '&' Name ';'
 
6550
 *
 
6551
 * [ WFC: Entity Declared ]
 
6552
 * In a document without any DTD, a document with only an internal DTD
 
6553
 * subset which contains no parameter entity references, or a document
 
6554
 * with "standalone='yes'", the Name given in the entity reference
 
6555
 * must match that in an entity declaration, except that well-formed
 
6556
 * documents need not declare any of the following entities: amp, lt,
 
6557
 * gt, apos, quot.  The declaration of a parameter entity must precede
 
6558
 * any reference to it.  Similarly, the declaration of a general entity
 
6559
 * must precede any reference to it which appears in a default value in an
 
6560
 * attribute-list declaration. Note that if entities are declared in the
 
6561
 * external subset or in external parameter entities, a non-validating
 
6562
 * processor is not obligated to read and process their declarations;
 
6563
 * for such documents, the rule that an entity must be declared is a
 
6564
 * well-formedness constraint only if standalone='yes'.
 
6565
 *
 
6566
 * [ WFC: Parsed Entity ]
 
6567
 * An entity reference must not contain the name of an unparsed entity
 
6568
 *
 
6569
 * Returns the xmlEntityPtr if found, or NULL otherwise.
 
6570
 */
 
6571
xmlEntityPtr
 
6572
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
 
6573
    const xmlChar *name;
 
6574
    xmlEntityPtr ent = NULL;
 
6575
 
 
6576
    GROW;
 
6577
    
 
6578
    if (RAW == '&') {
 
6579
        NEXT;
 
6580
        name = xmlParseName(ctxt);
 
6581
        if (name == NULL) {
 
6582
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6583
                           "xmlParseEntityRef: no name\n");
 
6584
        } else {
 
6585
            if (RAW == ';') {
 
6586
                NEXT;
 
6587
                /*
 
6588
                 * Ask first SAX for entity resolution, otherwise try the
 
6589
                 * predefined set.
 
6590
                 */
 
6591
                if (ctxt->sax != NULL) {
 
6592
                    if (ctxt->sax->getEntity != NULL)
 
6593
                        ent = ctxt->sax->getEntity(ctxt->userData, name);
 
6594
                    if ((ctxt->wellFormed == 1 ) && (ent == NULL))
 
6595
                        ent = xmlGetPredefinedEntity(name);
 
6596
                    if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
 
6597
                        (ctxt->userData==ctxt)) {
 
6598
                        ent = xmlSAX2GetEntity(ctxt, name);
 
6599
                    }
 
6600
                }
 
6601
                /*
 
6602
                 * [ WFC: Entity Declared ]
 
6603
                 * In a document without any DTD, a document with only an
 
6604
                 * internal DTD subset which contains no parameter entity
 
6605
                 * references, or a document with "standalone='yes'", the
 
6606
                 * Name given in the entity reference must match that in an
 
6607
                 * entity declaration, except that well-formed documents
 
6608
                 * need not declare any of the following entities: amp, lt,
 
6609
                 * gt, apos, quot.
 
6610
                 * The declaration of a parameter entity must precede any
 
6611
                 * reference to it.
 
6612
                 * Similarly, the declaration of a general entity must
 
6613
                 * precede any reference to it which appears in a default
 
6614
                 * value in an attribute-list declaration. Note that if
 
6615
                 * entities are declared in the external subset or in
 
6616
                 * external parameter entities, a non-validating processor
 
6617
                 * is not obligated to read and process their declarations;
 
6618
                 * for such documents, the rule that an entity must be
 
6619
                 * declared is a well-formedness constraint only if
 
6620
                 * standalone='yes'. 
 
6621
                 */
 
6622
                if (ent == NULL) {
 
6623
                    if ((ctxt->standalone == 1) ||
 
6624
                        ((ctxt->hasExternalSubset == 0) &&
 
6625
                         (ctxt->hasPErefs == 0))) {
 
6626
                        xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
6627
                                 "Entity '%s' not defined\n", name);
 
6628
                    } else {
 
6629
                        xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
6630
                                 "Entity '%s' not defined\n", name);
 
6631
                        if ((ctxt->inSubset == 0) &&
 
6632
                            (ctxt->sax != NULL) &&
 
6633
                            (ctxt->sax->reference != NULL)) {
 
6634
                            ctxt->sax->reference(ctxt->userData, name);
 
6635
                        }
 
6636
                    }
 
6637
                    ctxt->valid = 0;
 
6638
                }
 
6639
 
 
6640
                /*
 
6641
                 * [ WFC: Parsed Entity ]
 
6642
                 * An entity reference must not contain the name of an
 
6643
                 * unparsed entity
 
6644
                 */
 
6645
                else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 
6646
                    xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 
6647
                             "Entity reference to unparsed entity %s\n", name);
 
6648
                }
 
6649
 
 
6650
                /*
 
6651
                 * [ WFC: No External Entity References ]
 
6652
                 * Attribute values cannot contain direct or indirect
 
6653
                 * entity references to external entities.
 
6654
                 */
 
6655
                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
6656
                         (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
 
6657
                    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
 
6658
                         "Attribute references external entity '%s'\n", name);
 
6659
                }
 
6660
                /*
 
6661
                 * [ WFC: No < in Attribute Values ]
 
6662
                 * The replacement text of any entity referred to directly or
 
6663
                 * indirectly in an attribute value (other than "&lt;") must
 
6664
                 * not contain a <. 
 
6665
                 */
 
6666
                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
6667
                         (ent != NULL) &&
 
6668
                         (!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
 
6669
                         (ent->content != NULL) &&
 
6670
                         (xmlStrchr(ent->content, '<'))) {
 
6671
                    xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
6672
         "'<' in entity '%s' is not allowed in attributes values\n", name);
 
6673
                }
 
6674
 
 
6675
                /*
 
6676
                 * Internal check, no parameter entities here ...
 
6677
                 */
 
6678
                else {
 
6679
                    switch (ent->etype) {
 
6680
                        case XML_INTERNAL_PARAMETER_ENTITY:
 
6681
                        case XML_EXTERNAL_PARAMETER_ENTITY:
 
6682
                        xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
6683
                         "Attempt to reference the parameter entity '%s'\n",
 
6684
                                          name);
 
6685
                        break;
 
6686
                        default:
 
6687
                        break;
 
6688
                    }
 
6689
                }
 
6690
 
 
6691
                /*
 
6692
                 * [ WFC: No Recursion ]
 
6693
                 * A parsed entity must not contain a recursive reference
 
6694
                 * to itself, either directly or indirectly. 
 
6695
                 * Done somewhere else
 
6696
                 */
 
6697
 
 
6698
            } else {
 
6699
                xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
6700
            }
 
6701
        }
 
6702
    }
 
6703
    return(ent);
 
6704
}
 
6705
 
 
6706
/**
 
6707
 * xmlParseStringEntityRef:
 
6708
 * @ctxt:  an XML parser context
 
6709
 * @str:  a pointer to an index in the string
 
6710
 *
 
6711
 * parse ENTITY references declarations, but this version parses it from
 
6712
 * a string value.
 
6713
 *
 
6714
 * [68] EntityRef ::= '&' Name ';'
 
6715
 *
 
6716
 * [ WFC: Entity Declared ]
 
6717
 * In a document without any DTD, a document with only an internal DTD
 
6718
 * subset which contains no parameter entity references, or a document
 
6719
 * with "standalone='yes'", the Name given in the entity reference
 
6720
 * must match that in an entity declaration, except that well-formed
 
6721
 * documents need not declare any of the following entities: amp, lt,
 
6722
 * gt, apos, quot.  The declaration of a parameter entity must precede
 
6723
 * any reference to it.  Similarly, the declaration of a general entity
 
6724
 * must precede any reference to it which appears in a default value in an
 
6725
 * attribute-list declaration. Note that if entities are declared in the
 
6726
 * external subset or in external parameter entities, a non-validating
 
6727
 * processor is not obligated to read and process their declarations;
 
6728
 * for such documents, the rule that an entity must be declared is a
 
6729
 * well-formedness constraint only if standalone='yes'.
 
6730
 *
 
6731
 * [ WFC: Parsed Entity ]
 
6732
 * An entity reference must not contain the name of an unparsed entity
 
6733
 *
 
6734
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
 
6735
 * is updated to the current location in the string.
 
6736
 */
 
6737
xmlEntityPtr
 
6738
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
 
6739
    xmlChar *name;
 
6740
    const xmlChar *ptr;
 
6741
    xmlChar cur;
 
6742
    xmlEntityPtr ent = NULL;
 
6743
 
 
6744
    if ((str == NULL) || (*str == NULL))
 
6745
        return(NULL);
 
6746
    ptr = *str;
 
6747
    cur = *ptr;
 
6748
    if (cur == '&') {
 
6749
        ptr++;
 
6750
        cur = *ptr;
 
6751
        name = xmlParseStringName(ctxt, &ptr);
 
6752
        if (name == NULL) {
 
6753
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6754
                           "xmlParseStringEntityRef: no name\n");
 
6755
        } else {
 
6756
            if (*ptr == ';') {
 
6757
                ptr++;
 
6758
                /*
 
6759
                 * Ask first SAX for entity resolution, otherwise try the
 
6760
                 * predefined set.
 
6761
                 */
 
6762
                if (ctxt->sax != NULL) {
 
6763
                    if (ctxt->sax->getEntity != NULL)
 
6764
                        ent = ctxt->sax->getEntity(ctxt->userData, name);
 
6765
                    if (ent == NULL)
 
6766
                        ent = xmlGetPredefinedEntity(name);
 
6767
                    if ((ent == NULL) && (ctxt->userData==ctxt)) {
 
6768
                        ent = xmlSAX2GetEntity(ctxt, name);
 
6769
                    }
 
6770
                }
 
6771
                /*
 
6772
                 * [ WFC: Entity Declared ]
 
6773
                 * In a document without any DTD, a document with only an
 
6774
                 * internal DTD subset which contains no parameter entity
 
6775
                 * references, or a document with "standalone='yes'", the
 
6776
                 * Name given in the entity reference must match that in an
 
6777
                 * entity declaration, except that well-formed documents
 
6778
                 * need not declare any of the following entities: amp, lt,
 
6779
                 * gt, apos, quot.
 
6780
                 * The declaration of a parameter entity must precede any
 
6781
                 * reference to it.
 
6782
                 * Similarly, the declaration of a general entity must
 
6783
                 * precede any reference to it which appears in a default
 
6784
                 * value in an attribute-list declaration. Note that if
 
6785
                 * entities are declared in the external subset or in
 
6786
                 * external parameter entities, a non-validating processor
 
6787
                 * is not obligated to read and process their declarations;
 
6788
                 * for such documents, the rule that an entity must be
 
6789
                 * declared is a well-formedness constraint only if
 
6790
                 * standalone='yes'. 
 
6791
                 */
 
6792
                if (ent == NULL) {
 
6793
                    if ((ctxt->standalone == 1) ||
 
6794
                        ((ctxt->hasExternalSubset == 0) &&
 
6795
                         (ctxt->hasPErefs == 0))) {
 
6796
                        xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
6797
                                 "Entity '%s' not defined\n", name);
 
6798
                    } else {
 
6799
                        xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
6800
                                      "Entity '%s' not defined\n",
 
6801
                                      name);
 
6802
                    }
 
6803
                    /* TODO ? check regressions ctxt->valid = 0; */
 
6804
                }
 
6805
 
 
6806
                /*
 
6807
                 * [ WFC: Parsed Entity ]
 
6808
                 * An entity reference must not contain the name of an
 
6809
                 * unparsed entity
 
6810
                 */
 
6811
                else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 
6812
                    xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 
6813
                             "Entity reference to unparsed entity %s\n", name);
 
6814
                }
 
6815
 
 
6816
                /*
 
6817
                 * [ WFC: No External Entity References ]
 
6818
                 * Attribute values cannot contain direct or indirect
 
6819
                 * entity references to external entities.
 
6820
                 */
 
6821
                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
6822
                         (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
 
6823
                    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
 
6824
                     "Attribute references external entity '%s'\n", name);
 
6825
                }
 
6826
                /*
 
6827
                 * [ WFC: No < in Attribute Values ]
 
6828
                 * The replacement text of any entity referred to directly or
 
6829
                 * indirectly in an attribute value (other than "&lt;") must
 
6830
                 * not contain a <. 
 
6831
                 */
 
6832
                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
6833
                         (ent != NULL) &&
 
6834
                         (!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
 
6835
                         (ent->content != NULL) &&
 
6836
                         (xmlStrchr(ent->content, '<'))) {
 
6837
                    xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
6838
                 "'<' in entity '%s' is not allowed in attributes values\n",
 
6839
                                      name);
 
6840
                }
 
6841
 
 
6842
                /*
 
6843
                 * Internal check, no parameter entities here ...
 
6844
                 */
 
6845
                else {
 
6846
                    switch (ent->etype) {
 
6847
                        case XML_INTERNAL_PARAMETER_ENTITY:
 
6848
                        case XML_EXTERNAL_PARAMETER_ENTITY:
 
6849
                            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
6850
                         "Attempt to reference the parameter entity '%s'\n",
 
6851
                                              name);
 
6852
                        break;
 
6853
                        default:
 
6854
                        break;
 
6855
                    }
 
6856
                }
 
6857
 
 
6858
                /*
 
6859
                 * [ WFC: No Recursion ]
 
6860
                 * A parsed entity must not contain a recursive reference
 
6861
                 * to itself, either directly or indirectly. 
 
6862
                 * Done somewhere else
 
6863
                 */
 
6864
 
 
6865
            } else {
 
6866
                xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
6867
            }
 
6868
            xmlFree(name);
 
6869
        }
 
6870
    }
 
6871
    *str = ptr;
 
6872
    return(ent);
 
6873
}
 
6874
 
 
6875
/**
 
6876
 * xmlParsePEReference:
 
6877
 * @ctxt:  an XML parser context
 
6878
 *
 
6879
 * parse PEReference declarations
 
6880
 * The entity content is handled directly by pushing it's content as
 
6881
 * a new input stream.
 
6882
 *
 
6883
 * [69] PEReference ::= '%' Name ';'
 
6884
 *
 
6885
 * [ WFC: No Recursion ]
 
6886
 * A parsed entity must not contain a recursive
 
6887
 * reference to itself, either directly or indirectly. 
 
6888
 *
 
6889
 * [ WFC: Entity Declared ]
 
6890
 * In a document without any DTD, a document with only an internal DTD
 
6891
 * subset which contains no parameter entity references, or a document
 
6892
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
6893
 * entity must precede any reference to it...
 
6894
 *
 
6895
 * [ VC: Entity Declared ]
 
6896
 * In a document with an external subset or external parameter entities
 
6897
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
6898
 * must precede any reference to it...
 
6899
 *
 
6900
 * [ WFC: In DTD ]
 
6901
 * Parameter-entity references may only appear in the DTD.
 
6902
 * NOTE: misleading but this is handled.
 
6903
 */
 
6904
void
 
6905
xmlParsePEReference(xmlParserCtxtPtr ctxt)
 
6906
{
 
6907
    const xmlChar *name;
 
6908
    xmlEntityPtr entity = NULL;
 
6909
    xmlParserInputPtr input;
 
6910
 
 
6911
    if (RAW == '%') {
 
6912
        NEXT;
 
6913
        name = xmlParseName(ctxt);
 
6914
        if (name == NULL) {
 
6915
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6916
                           "xmlParsePEReference: no name\n");
 
6917
        } else {
 
6918
            if (RAW == ';') {
 
6919
                NEXT;
 
6920
                if ((ctxt->sax != NULL) &&
 
6921
                    (ctxt->sax->getParameterEntity != NULL))
 
6922
                    entity = ctxt->sax->getParameterEntity(ctxt->userData,
 
6923
                                                           name);
 
6924
                if (entity == NULL) {
 
6925
                    /*
 
6926
                     * [ WFC: Entity Declared ]
 
6927
                     * In a document without any DTD, a document with only an
 
6928
                     * internal DTD subset which contains no parameter entity
 
6929
                     * references, or a document with "standalone='yes'", ...
 
6930
                     * ... The declaration of a parameter entity must precede
 
6931
                     * any reference to it...
 
6932
                     */
 
6933
                    if ((ctxt->standalone == 1) ||
 
6934
                        ((ctxt->hasExternalSubset == 0) &&
 
6935
                         (ctxt->hasPErefs == 0))) {
 
6936
                        xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
6937
                                          "PEReference: %%%s; not found\n",
 
6938
                                          name);
 
6939
                    } else {
 
6940
                        /*
 
6941
                         * [ VC: Entity Declared ]
 
6942
                         * In a document with an external subset or external
 
6943
                         * parameter entities with "standalone='no'", ...
 
6944
                         * ... The declaration of a parameter entity must
 
6945
                         * precede any reference to it...
 
6946
                         */
 
6947
                        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
6948
                                      "PEReference: %%%s; not found\n",
 
6949
                                      name, NULL);
 
6950
                        ctxt->valid = 0;
 
6951
                    }
 
6952
                } else {
 
6953
                    /*
 
6954
                     * Internal checking in case the entity quest barfed
 
6955
                     */
 
6956
                    if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
 
6957
                        (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
 
6958
                        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
6959
                              "Internal: %%%s; is not a parameter entity\n",
 
6960
                                      name, NULL);
 
6961
                    } else if (ctxt->input->free != deallocblankswrapper) {
 
6962
                        input =
 
6963
                            xmlNewBlanksWrapperInputStream(ctxt, entity);
 
6964
                        xmlPushInput(ctxt, input);
 
6965
                    } else {
 
6966
                        /*
 
6967
                         * TODO !!!
 
6968
                         * handle the extra spaces added before and after
 
6969
                         * c.f. http://www.w3.org/TR/REC-xml#as-PE
 
6970
                         */
 
6971
                        input = xmlNewEntityInputStream(ctxt, entity);
 
6972
                        xmlPushInput(ctxt, input);
 
6973
                        if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
6974
                            (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
 
6975
                            (IS_BLANK_CH(NXT(5)))) {
 
6976
                            xmlParseTextDecl(ctxt);
 
6977
                            if (ctxt->errNo ==
 
6978
                                XML_ERR_UNSUPPORTED_ENCODING) {
 
6979
                                /*
 
6980
                                 * The XML REC instructs us to stop parsing
 
6981
                                 * right here
 
6982
                                 */
 
6983
                                ctxt->instate = XML_PARSER_EOF;
 
6984
                                return;
 
6985
                            }
 
6986
                        }
 
6987
                    }
 
6988
                }
 
6989
                ctxt->hasPErefs = 1;
 
6990
            } else {
 
6991
                xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
6992
            }
 
6993
        }
 
6994
    }
 
6995
}
 
6996
 
 
6997
/**
 
6998
 * xmlLoadEntityContent:
 
6999
 * @ctxt:  an XML parser context
 
7000
 * @entity: an unloaded system entity
 
7001
 *
 
7002
 * Load the original content of the given system entity from the
 
7003
 * ExternalID/SystemID given. This is to be used for Included in Literal
 
7004
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
 
7005
 *
 
7006
 * Returns 0 in case of success and -1 in case of failure
 
7007
 */
 
7008
static int
 
7009
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
 
7010
    xmlParserInputPtr input;
 
7011
    xmlBufferPtr buf;
 
7012
    int l, c;
 
7013
    int count = 0;
 
7014
 
 
7015
    if ((ctxt == NULL) || (entity == NULL) ||
 
7016
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
 
7017
         (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
 
7018
        (entity->content != NULL)) {
 
7019
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7020
                    "xmlLoadEntityContent parameter error");
 
7021
        return(-1);
 
7022
    }
 
7023
 
 
7024
    if (xmlParserDebugEntities)
 
7025
        xmlGenericError(xmlGenericErrorContext,
 
7026
                "Reading %s entity content input\n", entity->name);
 
7027
 
 
7028
    buf = xmlBufferCreate();
 
7029
    if (buf == NULL) {
 
7030
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7031
                    "xmlLoadEntityContent parameter error");
 
7032
        return(-1);
 
7033
    }
 
7034
 
 
7035
    input = xmlNewEntityInputStream(ctxt, entity);
 
7036
    if (input == NULL) {
 
7037
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7038
                    "xmlLoadEntityContent input error");
 
7039
        xmlBufferFree(buf);
 
7040
        return(-1);
 
7041
    }
 
7042
 
 
7043
    /*
 
7044
     * Push the entity as the current input, read char by char
 
7045
     * saving to the buffer until the end of the entity or an error
 
7046
     */
 
7047
    xmlPushInput(ctxt, input);
 
7048
    GROW;
 
7049
    c = CUR_CHAR(l);
 
7050
    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
 
7051
           (IS_CHAR(c))) {
 
7052
        xmlBufferAdd(buf, ctxt->input->cur, l);
 
7053
        if (count++ > 100) {
 
7054
            count = 0;
 
7055
            GROW;
 
7056
        }
 
7057
        NEXTL(l);
 
7058
        c = CUR_CHAR(l);
 
7059
    }
 
7060
 
 
7061
    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
 
7062
        xmlPopInput(ctxt);
 
7063
    } else if (!IS_CHAR(c)) {
 
7064
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
7065
                          "xmlLoadEntityContent: invalid char value %d\n",
 
7066
                          c);
 
7067
        xmlBufferFree(buf);
 
7068
        return(-1);
 
7069
    }
 
7070
    entity->content = buf->content;
 
7071
    buf->content = NULL;
 
7072
    xmlBufferFree(buf);
 
7073
 
 
7074
    return(0);
 
7075
}
 
7076
 
 
7077
/**
 
7078
 * xmlParseStringPEReference:
 
7079
 * @ctxt:  an XML parser context
 
7080
 * @str:  a pointer to an index in the string
 
7081
 *
 
7082
 * parse PEReference declarations
 
7083
 *
 
7084
 * [69] PEReference ::= '%' Name ';'
 
7085
 *
 
7086
 * [ WFC: No Recursion ]
 
7087
 * A parsed entity must not contain a recursive
 
7088
 * reference to itself, either directly or indirectly.
 
7089
 *
 
7090
 * [ WFC: Entity Declared ]
 
7091
 * In a document without any DTD, a document with only an internal DTD
 
7092
 * subset which contains no parameter entity references, or a document
 
7093
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
7094
 * entity must precede any reference to it...
 
7095
 *
 
7096
 * [ VC: Entity Declared ]
 
7097
 * In a document with an external subset or external parameter entities
 
7098
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
7099
 * must precede any reference to it...
 
7100
 *
 
7101
 * [ WFC: In DTD ]
 
7102
 * Parameter-entity references may only appear in the DTD.
 
7103
 * NOTE: misleading but this is handled.
 
7104
 *
 
7105
 * Returns the string of the entity content.
 
7106
 *         str is updated to the current value of the index
 
7107
 */
 
7108
xmlEntityPtr
 
7109
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 
7110
    const xmlChar *ptr;
 
7111
    xmlChar cur;
 
7112
    xmlChar *name;
 
7113
    xmlEntityPtr entity = NULL;
 
7114
 
 
7115
    if ((str == NULL) || (*str == NULL)) return(NULL);
 
7116
    ptr = *str;
 
7117
    cur = *ptr;
 
7118
    if (cur == '%') {
 
7119
        ptr++;
 
7120
        cur = *ptr;
 
7121
        name = xmlParseStringName(ctxt, &ptr);
 
7122
        if (name == NULL) {
 
7123
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7124
                           "xmlParseStringPEReference: no name\n");
 
7125
        } else {
 
7126
            cur = *ptr;
 
7127
            if (cur == ';') {
 
7128
                ptr++;
 
7129
                cur = *ptr;
 
7130
                if ((ctxt->sax != NULL) &&
 
7131
                    (ctxt->sax->getParameterEntity != NULL))
 
7132
                    entity = ctxt->sax->getParameterEntity(ctxt->userData,
 
7133
                                                           name);
 
7134
                if (entity == NULL) {
 
7135
                    /*
 
7136
                     * [ WFC: Entity Declared ]
 
7137
                     * In a document without any DTD, a document with only an
 
7138
                     * internal DTD subset which contains no parameter entity
 
7139
                     * references, or a document with "standalone='yes'", ...
 
7140
                     * ... The declaration of a parameter entity must precede
 
7141
                     * any reference to it...
 
7142
                     */
 
7143
                    if ((ctxt->standalone == 1) ||
 
7144
                        ((ctxt->hasExternalSubset == 0) &&
 
7145
                         (ctxt->hasPErefs == 0))) {
 
7146
                        xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7147
                             "PEReference: %%%s; not found\n", name);
 
7148
                    } else {
 
7149
                        /*
 
7150
                         * [ VC: Entity Declared ]
 
7151
                         * In a document with an external subset or external
 
7152
                         * parameter entities with "standalone='no'", ...
 
7153
                         * ... The declaration of a parameter entity must
 
7154
                         * precede any reference to it...
 
7155
                         */
 
7156
                        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7157
                                      "PEReference: %%%s; not found\n",
 
7158
                                      name, NULL);
 
7159
                        ctxt->valid = 0;
 
7160
                    }
 
7161
                } else {
 
7162
                    /*
 
7163
                     * Internal checking in case the entity quest barfed
 
7164
                     */
 
7165
                    if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
 
7166
                        (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
 
7167
                        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7168
                                      "%%%s; is not a parameter entity\n",
 
7169
                                      name, NULL);
 
7170
                    }
 
7171
                }
 
7172
                ctxt->hasPErefs = 1;
 
7173
            } else {
 
7174
                xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7175
            }
 
7176
            xmlFree(name);
 
7177
        }
 
7178
    }
 
7179
    *str = ptr;
 
7180
    return(entity);
 
7181
}
 
7182
 
 
7183
/**
 
7184
 * xmlParseDocTypeDecl:
 
7185
 * @ctxt:  an XML parser context
 
7186
 *
 
7187
 * parse a DOCTYPE declaration
 
7188
 *
 
7189
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? 
 
7190
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
 
7191
 *
 
7192
 * [ VC: Root Element Type ]
 
7193
 * The Name in the document type declaration must match the element
 
7194
 * type of the root element. 
 
7195
 */
 
7196
 
 
7197
void
 
7198
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
 
7199
    const xmlChar *name = NULL;
 
7200
    xmlChar *ExternalID = NULL;
 
7201
    xmlChar *URI = NULL;
 
7202
 
 
7203
    /*
 
7204
     * We know that '<!DOCTYPE' has been detected.
 
7205
     */
 
7206
    SKIP(9);
 
7207
 
 
7208
    SKIP_BLANKS;
 
7209
 
 
7210
    /*
 
7211
     * Parse the DOCTYPE name.
 
7212
     */
 
7213
    name = xmlParseName(ctxt);
 
7214
    if (name == NULL) {
 
7215
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7216
                       "xmlParseDocTypeDecl : no DOCTYPE name !\n");
 
7217
    }
 
7218
    ctxt->intSubName = name;
 
7219
 
 
7220
    SKIP_BLANKS;
 
7221
 
 
7222
    /*
 
7223
     * Check for SystemID and ExternalID
 
7224
     */
 
7225
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
 
7226
 
 
7227
    if ((URI != NULL) || (ExternalID != NULL)) {
 
7228
        ctxt->hasExternalSubset = 1;
 
7229
    }
 
7230
    ctxt->extSubURI = URI;
 
7231
    ctxt->extSubSystem = ExternalID;
 
7232
 
 
7233
    SKIP_BLANKS;
 
7234
 
 
7235
    /*
 
7236
     * Create and update the internal subset.
 
7237
     */
 
7238
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
 
7239
        (!ctxt->disableSAX))
 
7240
        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
 
7241
 
 
7242
    /*
 
7243
     * Is there any internal subset declarations ?
 
7244
     * they are handled separately in xmlParseInternalSubset()
 
7245
     */
 
7246
    if (RAW == '[')
 
7247
        return;
 
7248
 
 
7249
    /*
 
7250
     * We should be at the end of the DOCTYPE declaration.
 
7251
     */
 
7252
    if (RAW != '>') {
 
7253
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 
7254
    }
 
7255
    NEXT;
 
7256
}
 
7257
 
 
7258
/**
 
7259
 * xmlParseInternalSubset:
 
7260
 * @ctxt:  an XML parser context
 
7261
 *
 
7262
 * parse the internal subset declaration
 
7263
 *
 
7264
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
 
7265
 */
 
7266
 
 
7267
static void
 
7268
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
 
7269
    /*
 
7270
     * Is there any DTD definition ?
 
7271
     */
 
7272
    if (RAW == '[') {
 
7273
        ctxt->instate = XML_PARSER_DTD;
 
7274
        NEXT;
 
7275
        /*
 
7276
         * Parse the succession of Markup declarations and 
 
7277
         * PEReferences.
 
7278
         * Subsequence (markupdecl | PEReference | S)*
 
7279
         */
 
7280
        while (RAW != ']') {
 
7281
            const xmlChar *check = CUR_PTR;
 
7282
            unsigned int cons = ctxt->input->consumed;
 
7283
 
 
7284
            SKIP_BLANKS;
 
7285
            xmlParseMarkupDecl(ctxt);
 
7286
            xmlParsePEReference(ctxt);
 
7287
 
 
7288
            /*
 
7289
             * Pop-up of finished entities.
 
7290
             */
 
7291
            while ((RAW == 0) && (ctxt->inputNr > 1))
 
7292
                xmlPopInput(ctxt);
 
7293
 
 
7294
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
7295
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7296
             "xmlParseInternalSubset: error detected in Markup declaration\n");
 
7297
                break;
 
7298
            }
 
7299
        }
 
7300
        if (RAW == ']') { 
 
7301
            NEXT;
 
7302
            SKIP_BLANKS;
 
7303
        }
 
7304
    }
 
7305
 
 
7306
    /*
 
7307
     * We should be at the end of the DOCTYPE declaration.
 
7308
     */
 
7309
    if (RAW != '>') {
 
7310
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 
7311
    }
 
7312
    NEXT;
 
7313
}
 
7314
 
 
7315
#ifdef LIBXML_SAX1_ENABLED
 
7316
/**
 
7317
 * xmlParseAttribute:
 
7318
 * @ctxt:  an XML parser context
 
7319
 * @value:  a xmlChar ** used to store the value of the attribute
 
7320
 *
 
7321
 * parse an attribute
 
7322
 *
 
7323
 * [41] Attribute ::= Name Eq AttValue
 
7324
 *
 
7325
 * [ WFC: No External Entity References ]
 
7326
 * Attribute values cannot contain direct or indirect entity references
 
7327
 * to external entities.
 
7328
 *
 
7329
 * [ WFC: No < in Attribute Values ]
 
7330
 * The replacement text of any entity referred to directly or indirectly in
 
7331
 * an attribute value (other than "&lt;") must not contain a <. 
 
7332
 * 
 
7333
 * [ VC: Attribute Value Type ]
 
7334
 * The attribute must have been declared; the value must be of the type
 
7335
 * declared for it.
 
7336
 *
 
7337
 * [25] Eq ::= S? '=' S?
 
7338
 *
 
7339
 * With namespace:
 
7340
 *
 
7341
 * [NS 11] Attribute ::= QName Eq AttValue
 
7342
 *
 
7343
 * Also the case QName == xmlns:??? is handled independently as a namespace
 
7344
 * definition.
 
7345
 *
 
7346
 * Returns the attribute name, and the value in *value.
 
7347
 */
 
7348
 
 
7349
const xmlChar *
 
7350
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
 
7351
    const xmlChar *name;
 
7352
    xmlChar *val;
 
7353
 
 
7354
    *value = NULL;
 
7355
    GROW;
 
7356
    name = xmlParseName(ctxt);
 
7357
    if (name == NULL) {
 
7358
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7359
                       "error parsing attribute name\n");
 
7360
        return(NULL);
 
7361
    }
 
7362
 
 
7363
    /*
 
7364
     * read the value
 
7365
     */
 
7366
    SKIP_BLANKS;
 
7367
    if (RAW == '=') {
 
7368
        NEXT;
 
7369
        SKIP_BLANKS;
 
7370
        val = xmlParseAttValue(ctxt);
 
7371
        ctxt->instate = XML_PARSER_CONTENT;
 
7372
    } else {
 
7373
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 
7374
               "Specification mandate value for attribute %s\n", name);
 
7375
        return(NULL);
 
7376
    }
 
7377
 
 
7378
    /*
 
7379
     * Check that xml:lang conforms to the specification
 
7380
     * No more registered as an error, just generate a warning now
 
7381
     * since this was deprecated in XML second edition
 
7382
     */
 
7383
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
 
7384
        if (!xmlCheckLanguageID(val)) {
 
7385
            xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
 
7386
                          "Malformed value for xml:lang : %s\n",
 
7387
                          val, NULL);
 
7388
        }
 
7389
    }
 
7390
 
 
7391
    /*
 
7392
     * Check that xml:space conforms to the specification
 
7393
     */
 
7394
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
 
7395
        if (xmlStrEqual(val, BAD_CAST "default"))
 
7396
            *(ctxt->space) = 0;
 
7397
        else if (xmlStrEqual(val, BAD_CAST "preserve"))
 
7398
            *(ctxt->space) = 1;
 
7399
        else {
 
7400
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
 
7401
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
 
7402
                                 val, NULL);
 
7403
        }
 
7404
    }
 
7405
 
 
7406
    *value = val;
 
7407
    return(name);
 
7408
}
 
7409
 
 
7410
/**
 
7411
 * xmlParseStartTag:
 
7412
 * @ctxt:  an XML parser context
 
7413
 * 
 
7414
 * parse a start of tag either for rule element or
 
7415
 * EmptyElement. In both case we don't parse the tag closing chars.
 
7416
 *
 
7417
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
 
7418
 *
 
7419
 * [ WFC: Unique Att Spec ]
 
7420
 * No attribute name may appear more than once in the same start-tag or
 
7421
 * empty-element tag. 
 
7422
 *
 
7423
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 
7424
 *
 
7425
 * [ WFC: Unique Att Spec ]
 
7426
 * No attribute name may appear more than once in the same start-tag or
 
7427
 * empty-element tag. 
 
7428
 *
 
7429
 * With namespace:
 
7430
 *
 
7431
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
 
7432
 *
 
7433
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
 
7434
 *
 
7435
 * Returns the element name parsed
 
7436
 */
 
7437
 
 
7438
const xmlChar *
 
7439
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
 
7440
    const xmlChar *name;
 
7441
    const xmlChar *attname;
 
7442
    xmlChar *attvalue;
 
7443
    const xmlChar **atts = ctxt->atts;
 
7444
    int nbatts = 0;
 
7445
    int maxatts = ctxt->maxatts;
 
7446
    int i;
 
7447
 
 
7448
    if (RAW != '<') return(NULL);
 
7449
    NEXT1;
 
7450
 
 
7451
    name = xmlParseName(ctxt);
 
7452
    if (name == NULL) {
 
7453
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7454
             "xmlParseStartTag: invalid element name\n");
 
7455
        return(NULL);
 
7456
    }
 
7457
 
 
7458
    /*
 
7459
     * Now parse the attributes, it ends up with the ending
 
7460
     *
 
7461
     * (S Attribute)* S?
 
7462
     */
 
7463
    SKIP_BLANKS;
 
7464
    GROW;
 
7465
 
 
7466
    while ((RAW != '>') && 
 
7467
           ((RAW != '/') || (NXT(1) != '>')) &&
 
7468
           (IS_BYTE_CHAR(RAW))) {
 
7469
        const xmlChar *q = CUR_PTR;
 
7470
        unsigned int cons = ctxt->input->consumed;
 
7471
 
 
7472
        attname = xmlParseAttribute(ctxt, &attvalue);
 
7473
        if ((attname != NULL) && (attvalue != NULL)) {
 
7474
            /*
 
7475
             * [ WFC: Unique Att Spec ]
 
7476
             * No attribute name may appear more than once in the same
 
7477
             * start-tag or empty-element tag. 
 
7478
             */
 
7479
            for (i = 0; i < nbatts;i += 2) {
 
7480
                if (xmlStrEqual(atts[i], attname)) {
 
7481
                    xmlErrAttributeDup(ctxt, NULL, attname);
 
7482
                    xmlFree(attvalue);
 
7483
                    goto failed;
 
7484
                }
 
7485
            }
 
7486
            /*
 
7487
             * Add the pair to atts
 
7488
             */
 
7489
            if (atts == NULL) {
 
7490
                maxatts = 22; /* allow for 10 attrs by default */
 
7491
                atts = (const xmlChar **)
 
7492
                       xmlMalloc(maxatts * sizeof(xmlChar *));
 
7493
                if (atts == NULL) {
 
7494
                    xmlErrMemory(ctxt, NULL);
 
7495
                    if (attvalue != NULL)
 
7496
                        xmlFree(attvalue);
 
7497
                    goto failed;
 
7498
                }
 
7499
                ctxt->atts = atts;
 
7500
                ctxt->maxatts = maxatts;
 
7501
            } else if (nbatts + 4 > maxatts) {
 
7502
                const xmlChar **n;
 
7503
 
 
7504
                maxatts *= 2;
 
7505
                n = (const xmlChar **) xmlRealloc((void *) atts,
 
7506
                                             maxatts * sizeof(const xmlChar *));
 
7507
                if (n == NULL) {
 
7508
                    xmlErrMemory(ctxt, NULL);
 
7509
                    if (attvalue != NULL)
 
7510
                        xmlFree(attvalue);
 
7511
                    goto failed;
 
7512
                }
 
7513
                atts = n;
 
7514
                ctxt->atts = atts;
 
7515
                ctxt->maxatts = maxatts;
 
7516
            }
 
7517
            atts[nbatts++] = attname;
 
7518
            atts[nbatts++] = attvalue;
 
7519
            atts[nbatts] = NULL;
 
7520
            atts[nbatts + 1] = NULL;
 
7521
        } else {
 
7522
            if (attvalue != NULL)
 
7523
                xmlFree(attvalue);
 
7524
        }
 
7525
 
 
7526
failed:     
 
7527
 
 
7528
        GROW
 
7529
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 
7530
            break;
 
7531
        if (!IS_BLANK_CH(RAW)) {
 
7532
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
7533
                           "attributes construct error\n");
 
7534
        }
 
7535
        SKIP_BLANKS;
 
7536
        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
 
7537
            (attname == NULL) && (attvalue == NULL)) {
 
7538
            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
 
7539
                           "xmlParseStartTag: problem parsing attributes\n");
 
7540
            break;
 
7541
        }
 
7542
        SHRINK;
 
7543
        GROW;
 
7544
    }
 
7545
 
 
7546
    /*
 
7547
     * SAX: Start of Element !
 
7548
     */
 
7549
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
 
7550
        (!ctxt->disableSAX)) {
 
7551
        if (nbatts > 0)
 
7552
            ctxt->sax->startElement(ctxt->userData, name, atts);
 
7553
        else
 
7554
            ctxt->sax->startElement(ctxt->userData, name, NULL);
 
7555
    }
 
7556
 
 
7557
    if (atts != NULL) {
 
7558
        /* Free only the content strings */
 
7559
        for (i = 1;i < nbatts;i+=2)
 
7560
            if (atts[i] != NULL)
 
7561
               xmlFree((xmlChar *) atts[i]);
 
7562
    }
 
7563
    return(name);
 
7564
}
 
7565
 
 
7566
/**
 
7567
 * xmlParseEndTag1:
 
7568
 * @ctxt:  an XML parser context
 
7569
 * @line:  line of the start tag
 
7570
 * @nsNr:  number of namespaces on the start tag
 
7571
 *
 
7572
 * parse an end of tag
 
7573
 *
 
7574
 * [42] ETag ::= '</' Name S? '>'
 
7575
 *
 
7576
 * With namespace
 
7577
 *
 
7578
 * [NS 9] ETag ::= '</' QName S? '>'
 
7579
 */
 
7580
 
 
7581
static void
 
7582
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
 
7583
    const xmlChar *name;
 
7584
 
 
7585
    GROW;
 
7586
    if ((RAW != '<') || (NXT(1) != '/')) {
 
7587
        xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
 
7588
                       "xmlParseEndTag: '</' not found\n");
 
7589
        return;
 
7590
    }
 
7591
    SKIP(2);
 
7592
 
 
7593
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
 
7594
 
 
7595
    /*
 
7596
     * We should definitely be at the ending "S? '>'" part
 
7597
     */
 
7598
    GROW;
 
7599
    SKIP_BLANKS;
 
7600
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 
7601
        xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
7602
    } else
 
7603
        NEXT1;
 
7604
 
 
7605
    /*
 
7606
     * [ WFC: Element Type Match ]
 
7607
     * The Name in an element's end-tag must match the element type in the
 
7608
     * start-tag. 
 
7609
     *
 
7610
     */
 
7611
    if (name != (xmlChar*)1) {
 
7612
        if (name == NULL) name = BAD_CAST "unparseable";
 
7613
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
 
7614
                     "Opening and ending tag mismatch: %s line %d and %s\n",
 
7615
                                ctxt->name, line, name);
 
7616
    }
 
7617
 
 
7618
    /*
 
7619
     * SAX: End of Tag
 
7620
     */
 
7621
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
 
7622
        (!ctxt->disableSAX))
 
7623
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
 
7624
 
 
7625
    namePop(ctxt);
 
7626
    spacePop(ctxt);
 
7627
    return;
 
7628
}
 
7629
 
 
7630
/**
 
7631
 * xmlParseEndTag:
 
7632
 * @ctxt:  an XML parser context
 
7633
 *
 
7634
 * parse an end of tag
 
7635
 *
 
7636
 * [42] ETag ::= '</' Name S? '>'
 
7637
 *
 
7638
 * With namespace
 
7639
 *
 
7640
 * [NS 9] ETag ::= '</' QName S? '>'
 
7641
 */
 
7642
 
 
7643
void
 
7644
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
 
7645
    xmlParseEndTag1(ctxt, 0);
 
7646
}
 
7647
#endif /* LIBXML_SAX1_ENABLED */
 
7648
 
 
7649
/************************************************************************
 
7650
 *                                                                      *
 
7651
 *                    SAX 2 specific operations                         *
 
7652
 *                                                                      *
 
7653
 ************************************************************************/
 
7654
 
 
7655
static const xmlChar *
 
7656
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
 
7657
    int len = 0, l;
 
7658
    int c;
 
7659
    int count = 0;
 
7660
 
 
7661
    /*
 
7662
     * Handler for more complex cases
 
7663
     */
 
7664
    GROW;
 
7665
    c = CUR_CHAR(l);
 
7666
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
7667
        (!IS_LETTER(c) && (c != '_'))) {
 
7668
        return(NULL);
 
7669
    }
 
7670
 
 
7671
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 
7672
           ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
7673
            (c == '.') || (c == '-') || (c == '_') ||
 
7674
            (IS_COMBINING(c)) ||
 
7675
            (IS_EXTENDER(c)))) {
 
7676
        if (count++ > 100) {
 
7677
            count = 0;
 
7678
            GROW;
 
7679
        }
 
7680
        len += l;
 
7681
        NEXTL(l);
 
7682
        c = CUR_CHAR(l);
 
7683
    }
 
7684
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 
7685
}
 
7686
 
 
7687
/*
 
7688
 * xmlGetNamespace:
 
7689
 * @ctxt:  an XML parser context
 
7690
 * @prefix:  the prefix to lookup
 
7691
 *
 
7692
 * Lookup the namespace name for the @prefix (which ca be NULL)
 
7693
 * The prefix must come from the @ctxt->dict dictionnary
 
7694
 *
 
7695
 * Returns the namespace name or NULL if not bound
 
7696
 */
 
7697
static const xmlChar *
 
7698
xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
 
7699
    int i;
 
7700
 
 
7701
    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
 
7702
    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
 
7703
        if (ctxt->nsTab[i] == prefix) {
 
7704
            if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
 
7705
                return(NULL);
 
7706
            return(ctxt->nsTab[i + 1]);
 
7707
        }
 
7708
    return(NULL);
 
7709
}
 
7710
 
 
7711
/**
 
7712
 * xmlParseNCName:
 
7713
 * @ctxt:  an XML parser context
 
7714
 * @len:  lenght of the string parsed
 
7715
 *
 
7716
 * parse an XML name.
 
7717
 *
 
7718
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
 
7719
 *                      CombiningChar | Extender
 
7720
 *
 
7721
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
 
7722
 *
 
7723
 * Returns the Name parsed or NULL
 
7724
 */
 
7725
 
 
7726
static const xmlChar *
 
7727
xmlParseNCName(xmlParserCtxtPtr ctxt) {
 
7728
    const xmlChar *in;
 
7729
    const xmlChar *ret;
 
7730
    int count = 0;
 
7731
 
 
7732
    /*
 
7733
     * Accelerator for simple ASCII names
 
7734
     */
 
7735
    in = ctxt->input->cur;
 
7736
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
 
7737
        ((*in >= 0x41) && (*in <= 0x5A)) ||
 
7738
        (*in == '_')) {
 
7739
        in++;
 
7740
        while (((*in >= 0x61) && (*in <= 0x7A)) ||
 
7741
               ((*in >= 0x41) && (*in <= 0x5A)) ||
 
7742
               ((*in >= 0x30) && (*in <= 0x39)) ||
 
7743
               (*in == '_') || (*in == '-') ||
 
7744
               (*in == '.'))
 
7745
            in++;
 
7746
        if ((*in > 0) && (*in < 0x80)) {
 
7747
            count = in - ctxt->input->cur;
 
7748
            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 
7749
            ctxt->input->cur = in;
 
7750
            ctxt->nbChars += count;
 
7751
            ctxt->input->col += count;
 
7752
            if (ret == NULL) {
 
7753
                xmlErrMemory(ctxt, NULL);
 
7754
            }
 
7755
            return(ret);
 
7756
        }
 
7757
    }
 
7758
    return(xmlParseNCNameComplex(ctxt));
 
7759
}
 
7760
 
 
7761
/**
 
7762
 * xmlParseQName:
 
7763
 * @ctxt:  an XML parser context
 
7764
 * @prefix:  pointer to store the prefix part
 
7765
 *
 
7766
 * parse an XML Namespace QName
 
7767
 *
 
7768
 * [6]  QName  ::= (Prefix ':')? LocalPart
 
7769
 * [7]  Prefix  ::= NCName
 
7770
 * [8]  LocalPart  ::= NCName
 
7771
 *
 
7772
 * Returns the Name parsed or NULL
 
7773
 */
 
7774
 
 
7775
static const xmlChar *
 
7776
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
 
7777
    const xmlChar *l, *p;
 
7778
 
 
7779
    GROW;
 
7780
 
 
7781
    l = xmlParseNCName(ctxt);
 
7782
    if (l == NULL) {
 
7783
        if (CUR == ':') {
 
7784
            l = xmlParseName(ctxt);
 
7785
            if (l != NULL) {
 
7786
                xmlNsErr(ctxt, XML_NS_ERR_QNAME, 
 
7787
                         "Failed to parse QName '%s'\n", l, NULL, NULL);
 
7788
                *prefix = NULL;
 
7789
                return(l);
 
7790
            }
 
7791
        }
 
7792
        return(NULL);
 
7793
    }
 
7794
    if (CUR == ':') {
 
7795
        NEXT;
 
7796
        p = l;
 
7797
        l = xmlParseNCName(ctxt);
 
7798
        if (l == NULL) {
 
7799
            xmlChar *tmp;
 
7800
 
 
7801
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
7802
                     "Failed to parse QName '%s:'\n", p, NULL, NULL);
 
7803
            tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
 
7804
            p = xmlDictLookup(ctxt->dict, tmp, -1);
 
7805
            if (tmp != NULL) xmlFree(tmp);
 
7806
            *prefix = NULL;
 
7807
            return(p);
 
7808
        }
 
7809
        if (CUR == ':') {
 
7810
            xmlChar *tmp;
 
7811
 
 
7812
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
7813
                     "Failed to parse QName '%s:%s:'\n", p, l, NULL);
 
7814
            NEXT;
 
7815
            tmp = (xmlChar *) xmlParseName(ctxt);
 
7816
            if (tmp != NULL) {
 
7817
                tmp = xmlBuildQName(tmp, l, NULL, 0);
 
7818
                l = xmlDictLookup(ctxt->dict, tmp, -1);
 
7819
                if (tmp != NULL) xmlFree(tmp);
 
7820
                *prefix = p;
 
7821
                return(l);
 
7822
            }
 
7823
            tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
 
7824
            l = xmlDictLookup(ctxt->dict, tmp, -1);
 
7825
            if (tmp != NULL) xmlFree(tmp);
 
7826
            *prefix = p;
 
7827
            return(l);
 
7828
        }
 
7829
        *prefix = p;
 
7830
    } else
 
7831
        *prefix = NULL;
 
7832
    return(l);
 
7833
}
 
7834
 
 
7835
/**
 
7836
 * xmlParseQNameAndCompare:
 
7837
 * @ctxt:  an XML parser context
 
7838
 * @name:  the localname
 
7839
 * @prefix:  the prefix, if any.
 
7840
 *
 
7841
 * parse an XML name and compares for match
 
7842
 * (specialized for endtag parsing)
 
7843
 *
 
7844
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
 
7845
 * and the name for mismatch
 
7846
 */
 
7847
 
 
7848
static const xmlChar *
 
7849
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
 
7850
                        xmlChar const *prefix) {
 
7851
    const xmlChar *cmp = name;
 
7852
    const xmlChar *in;
 
7853
    const xmlChar *ret;
 
7854
    const xmlChar *prefix2;
 
7855
 
 
7856
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
 
7857
 
 
7858
    GROW;
 
7859
    in = ctxt->input->cur;
 
7860
    
 
7861
    cmp = prefix;
 
7862
    while (*in != 0 && *in == *cmp) {
 
7863
        ++in;
 
7864
        ++cmp;
 
7865
    }
 
7866
    if ((*cmp == 0) && (*in == ':')) {
 
7867
        in++;
 
7868
        cmp = name;
 
7869
        while (*in != 0 && *in == *cmp) {
 
7870
            ++in;
 
7871
            ++cmp;
 
7872
        }
 
7873
        if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 
7874
            /* success */
 
7875
            ctxt->input->cur = in;
 
7876
            return((const xmlChar*) 1);
 
7877
        }
 
7878
    }
 
7879
    /*
 
7880
     * all strings coms from the dictionary, equality can be done directly
 
7881
     */
 
7882
    ret = xmlParseQName (ctxt, &prefix2);
 
7883
    if ((ret == name) && (prefix == prefix2))
 
7884
        return((const xmlChar*) 1);
 
7885
    return ret;
 
7886
}
 
7887
 
 
7888
/**
 
7889
 * xmlParseAttValueInternal:
 
7890
 * @ctxt:  an XML parser context
 
7891
 * @len:  attribute len result
 
7892
 * @alloc:  whether the attribute was reallocated as a new string
 
7893
 * @normalize:  if 1 then further non-CDATA normalization must be done
 
7894
 *
 
7895
 * parse a value for an attribute.
 
7896
 * NOTE: if no normalization is needed, the routine will return pointers
 
7897
 *       directly from the data buffer.
 
7898
 *
 
7899
 * 3.3.3 Attribute-Value Normalization:
 
7900
 * Before the value of an attribute is passed to the application or
 
7901
 * checked for validity, the XML processor must normalize it as follows: 
 
7902
 * - a character reference is processed by appending the referenced
 
7903
 *   character to the attribute value
 
7904
 * - an entity reference is processed by recursively processing the
 
7905
 *   replacement text of the entity 
 
7906
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
 
7907
 *   appending #x20 to the normalized value, except that only a single
 
7908
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
 
7909
 *   parsed entity or the literal entity value of an internal parsed entity 
 
7910
 * - other characters are processed by appending them to the normalized value 
 
7911
 * If the declared value is not CDATA, then the XML processor must further
 
7912
 * process the normalized attribute value by discarding any leading and
 
7913
 * trailing space (#x20) characters, and by replacing sequences of space
 
7914
 * (#x20) characters by a single space (#x20) character.  
 
7915
 * All attributes for which no declaration has been read should be treated
 
7916
 * by a non-validating parser as if declared CDATA.
 
7917
 *
 
7918
 * Returns the AttValue parsed or NULL. The value has to be freed by the
 
7919
 *     caller if it was copied, this can be detected by val[*len] == 0.
 
7920
 */
 
7921
 
 
7922
static xmlChar *
 
7923
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
 
7924
                         int normalize)
 
7925
{
 
7926
    xmlChar limit = 0;
 
7927
    const xmlChar *in = NULL, *start, *end, *last;
 
7928
    xmlChar *ret = NULL;
 
7929
 
 
7930
    GROW;
 
7931
    in = (xmlChar *) CUR_PTR;
 
7932
    if (*in != '"' && *in != '\'') {
 
7933
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 
7934
        return (NULL);
 
7935
    }
 
7936
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
7937
 
 
7938
    /*
 
7939
     * try to handle in this routine the most common case where no
 
7940
     * allocation of a new string is required and where content is
 
7941
     * pure ASCII.
 
7942
     */
 
7943
    limit = *in++;
 
7944
    end = ctxt->input->end;
 
7945
    start = in;
 
7946
    if (in >= end) {
 
7947
        const xmlChar *oldbase = ctxt->input->base;
 
7948
        GROW;
 
7949
        if (oldbase != ctxt->input->base) {
 
7950
            long delta = ctxt->input->base - oldbase;
 
7951
            start = start + delta;
 
7952
            in = in + delta;
 
7953
        }
 
7954
        end = ctxt->input->end;
 
7955
    }
 
7956
    if (normalize) {
 
7957
        /*
 
7958
         * Skip any leading spaces
 
7959
         */
 
7960
        while ((in < end) && (*in != limit) && 
 
7961
               ((*in == 0x20) || (*in == 0x9) ||
 
7962
                (*in == 0xA) || (*in == 0xD))) {
 
7963
            in++;
 
7964
            start = in;
 
7965
            if (in >= end) {
 
7966
                const xmlChar *oldbase = ctxt->input->base;
 
7967
                GROW;
 
7968
                if (oldbase != ctxt->input->base) {
 
7969
                    long delta = ctxt->input->base - oldbase;
 
7970
                    start = start + delta;
 
7971
                    in = in + delta;
 
7972
                }
 
7973
                end = ctxt->input->end;
 
7974
            }
 
7975
        }
 
7976
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
 
7977
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
 
7978
            if ((*in++ == 0x20) && (*in == 0x20)) break;
 
7979
            if (in >= end) {
 
7980
                const xmlChar *oldbase = ctxt->input->base;
 
7981
                GROW;
 
7982
                if (oldbase != ctxt->input->base) {
 
7983
                    long delta = ctxt->input->base - oldbase;
 
7984
                    start = start + delta;
 
7985
                    in = in + delta;
 
7986
                }
 
7987
                end = ctxt->input->end;
 
7988
            }
 
7989
        }
 
7990
        last = in;
 
7991
        /*
 
7992
         * skip the trailing blanks
 
7993
         */
 
7994
        while ((last[-1] == 0x20) && (last > start)) last--;
 
7995
        while ((in < end) && (*in != limit) && 
 
7996
               ((*in == 0x20) || (*in == 0x9) ||
 
7997
                (*in == 0xA) || (*in == 0xD))) {
 
7998
            in++;
 
7999
            if (in >= end) {
 
8000
                const xmlChar *oldbase = ctxt->input->base;
 
8001
                GROW;
 
8002
                if (oldbase != ctxt->input->base) {
 
8003
                    long delta = ctxt->input->base - oldbase;
 
8004
                    start = start + delta;
 
8005
                    in = in + delta;
 
8006
                    last = last + delta;
 
8007
                }
 
8008
                end = ctxt->input->end;
 
8009
            }
 
8010
        }
 
8011
        if (*in != limit) goto need_complex;
 
8012
    } else {
 
8013
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
 
8014
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
 
8015
            in++;
 
8016
            if (in >= end) {
 
8017
                const xmlChar *oldbase = ctxt->input->base;
 
8018
                GROW;
 
8019
                if (oldbase != ctxt->input->base) {
 
8020
                    long delta = ctxt->input->base - oldbase;
 
8021
                    start = start + delta;
 
8022
                    in = in + delta;
 
8023
                }
 
8024
                end = ctxt->input->end;
 
8025
            }
 
8026
        }
 
8027
        last = in;
 
8028
        if (*in != limit) goto need_complex;
 
8029
    }
 
8030
    in++;
 
8031
    if (len != NULL) {
 
8032
        *len = last - start;
 
8033
        ret = (xmlChar *) start;
 
8034
    } else {
 
8035
        if (alloc) *alloc = 1;
 
8036
        ret = xmlStrndup(start, last - start);
 
8037
    }
 
8038
    CUR_PTR = in;
 
8039
    if (alloc) *alloc = 0;
 
8040
    return ret;
 
8041
need_complex:
 
8042
    if (alloc) *alloc = 1;
 
8043
    return xmlParseAttValueComplex(ctxt, len, normalize);
 
8044
}
 
8045
 
 
8046
/**
 
8047
 * xmlParseAttribute2:
 
8048
 * @ctxt:  an XML parser context
 
8049
 * @pref:  the element prefix
 
8050
 * @elem:  the element name
 
8051
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
 
8052
 * @value:  a xmlChar ** used to store the value of the attribute
 
8053
 * @len:  an int * to save the length of the attribute
 
8054
 * @alloc:  an int * to indicate if the attribute was allocated
 
8055
 *
 
8056
 * parse an attribute in the new SAX2 framework.
 
8057
 *
 
8058
 * Returns the attribute name, and the value in *value, .
 
8059
 */
 
8060
 
 
8061
static const xmlChar *
 
8062
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
 
8063
                   const xmlChar * pref, const xmlChar * elem,
 
8064
                   const xmlChar ** prefix, xmlChar ** value,
 
8065
                   int *len, int *alloc)
 
8066
{
 
8067
    const xmlChar *name;
 
8068
    xmlChar *val, *internal_val = NULL;
 
8069
    int normalize = 0;
 
8070
 
 
8071
    *value = NULL;
 
8072
    GROW;
 
8073
    name = xmlParseQName(ctxt, prefix);
 
8074
    if (name == NULL) {
 
8075
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8076
                       "error parsing attribute name\n");
 
8077
        return (NULL);
 
8078
    }
 
8079
 
 
8080
    /*
 
8081
     * get the type if needed
 
8082
     */
 
8083
    if (ctxt->attsSpecial != NULL) {
 
8084
        int type;
 
8085
 
 
8086
        type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
 
8087
                                            pref, elem, *prefix, name);
 
8088
        if (type != 0)
 
8089
            normalize = 1;
 
8090
    }
 
8091
 
 
8092
    /*
 
8093
     * read the value
 
8094
     */
 
8095
    SKIP_BLANKS;
 
8096
    if (RAW == '=') {
 
8097
        NEXT;
 
8098
        SKIP_BLANKS;
 
8099
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
 
8100
        if (normalize) {
 
8101
            /*
 
8102
             * Sometimes a second normalisation pass for spaces is needed
 
8103
             * but that only happens if charrefs or entities refernces
 
8104
             * have been used in the attribute value, i.e. the attribute
 
8105
             * value have been extracted in an allocated string already.
 
8106
             */
 
8107
            if (*alloc) {
 
8108
                const xmlChar *val2;
 
8109
 
 
8110
                val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
 
8111
                if (val2 != NULL) {
 
8112
                    xmlFree(val);
 
8113
                    val = (xmlChar *) val2;
 
8114
                }
 
8115
            }
 
8116
        }
 
8117
        ctxt->instate = XML_PARSER_CONTENT;
 
8118
    } else {
 
8119
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 
8120
                          "Specification mandate value for attribute %s\n",
 
8121
                          name);
 
8122
        return (NULL);
 
8123
    }
 
8124
 
 
8125
    if (*prefix == ctxt->str_xml) {
 
8126
        /*
 
8127
         * Check that xml:lang conforms to the specification
 
8128
         * No more registered as an error, just generate a warning now
 
8129
         * since this was deprecated in XML second edition
 
8130
         */
 
8131
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
 
8132
            internal_val = xmlStrndup(val, *len);
 
8133
            if (!xmlCheckLanguageID(internal_val)) {
 
8134
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
 
8135
                              "Malformed value for xml:lang : %s\n",
 
8136
                              internal_val, NULL);
 
8137
            }
 
8138
        }
 
8139
 
 
8140
        /*
 
8141
         * Check that xml:space conforms to the specification
 
8142
         */
 
8143
        if (xmlStrEqual(name, BAD_CAST "space")) {
 
8144
            internal_val = xmlStrndup(val, *len);
 
8145
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
 
8146
                *(ctxt->space) = 0;
 
8147
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
 
8148
                *(ctxt->space) = 1;
 
8149
            else {
 
8150
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
 
8151
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
 
8152
                              internal_val, NULL);
 
8153
            }
 
8154
        }
 
8155
        if (internal_val) {
 
8156
            xmlFree(internal_val);
 
8157
        }
 
8158
    }
 
8159
 
 
8160
    *value = val;
 
8161
    return (name);
 
8162
}
 
8163
/**
 
8164
 * xmlParseStartTag2:
 
8165
 * @ctxt:  an XML parser context
 
8166
 * 
 
8167
 * parse a start of tag either for rule element or
 
8168
 * EmptyElement. In both case we don't parse the tag closing chars.
 
8169
 * This routine is called when running SAX2 parsing
 
8170
 *
 
8171
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
 
8172
 *
 
8173
 * [ WFC: Unique Att Spec ]
 
8174
 * No attribute name may appear more than once in the same start-tag or
 
8175
 * empty-element tag. 
 
8176
 *
 
8177
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 
8178
 *
 
8179
 * [ WFC: Unique Att Spec ]
 
8180
 * No attribute name may appear more than once in the same start-tag or
 
8181
 * empty-element tag. 
 
8182
 *
 
8183
 * With namespace:
 
8184
 *
 
8185
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
 
8186
 *
 
8187
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
 
8188
 *
 
8189
 * Returns the element name parsed
 
8190
 */
 
8191
 
 
8192
static const xmlChar *
 
8193
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
 
8194
                  const xmlChar **URI, int *tlen) {
 
8195
    const xmlChar *localname;
 
8196
    const xmlChar *prefix;
 
8197
    const xmlChar *attname;
 
8198
    const xmlChar *aprefix;
 
8199
    const xmlChar *nsname;
 
8200
    xmlChar *attvalue;
 
8201
    const xmlChar **atts = ctxt->atts;
 
8202
    int maxatts = ctxt->maxatts;
 
8203
    int nratts, nbatts, nbdef;
 
8204
    int i, j, nbNs, attval, oldline, oldcol;
 
8205
    const xmlChar *base;
 
8206
    unsigned long cur;
 
8207
    int nsNr = ctxt->nsNr;
 
8208
 
 
8209
    if (RAW != '<') return(NULL);
 
8210
    NEXT1;
 
8211
 
 
8212
    /*
 
8213
     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
 
8214
     *       point since the attribute values may be stored as pointers to
 
8215
     *       the buffer and calling SHRINK would destroy them !
 
8216
     *       The Shrinking is only possible once the full set of attribute
 
8217
     *       callbacks have been done.
 
8218
     */
 
8219
reparse:
 
8220
    SHRINK;
 
8221
    base = ctxt->input->base;
 
8222
    cur = ctxt->input->cur - ctxt->input->base;
 
8223
    oldline = ctxt->input->line;
 
8224
    oldcol = ctxt->input->col;
 
8225
    nbatts = 0;
 
8226
    nratts = 0;
 
8227
    nbdef = 0;
 
8228
    nbNs = 0;
 
8229
    attval = 0;
 
8230
    /* Forget any namespaces added during an earlier parse of this element. */
 
8231
    ctxt->nsNr = nsNr;
 
8232
 
 
8233
    localname = xmlParseQName(ctxt, &prefix);
 
8234
    if (localname == NULL) {
 
8235
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8236
                       "StartTag: invalid element name\n");
 
8237
        return(NULL);
 
8238
    }
 
8239
    *tlen = ctxt->input->cur - ctxt->input->base - cur;
 
8240
 
 
8241
    /*
 
8242
     * Now parse the attributes, it ends up with the ending
 
8243
     *
 
8244
     * (S Attribute)* S?
 
8245
     */
 
8246
    SKIP_BLANKS;
 
8247
    GROW;
 
8248
    if (ctxt->input->base != base) goto base_changed;
 
8249
 
 
8250
    while ((RAW != '>') && 
 
8251
           ((RAW != '/') || (NXT(1) != '>')) &&
 
8252
           (IS_BYTE_CHAR(RAW))) {
 
8253
        const xmlChar *q = CUR_PTR;
 
8254
        unsigned int cons = ctxt->input->consumed;
 
8255
        int len = -1, alloc = 0;
 
8256
 
 
8257
        attname = xmlParseAttribute2(ctxt, prefix, localname,
 
8258
                                     &aprefix, &attvalue, &len, &alloc);
 
8259
        if (ctxt->input->base != base) {
 
8260
            if ((attvalue != NULL) && (alloc != 0))
 
8261
                xmlFree(attvalue);
 
8262
            attvalue = NULL;
 
8263
            goto base_changed;
 
8264
        }
 
8265
        if ((attname != NULL) && (attvalue != NULL)) {
 
8266
            if (len < 0) len = xmlStrlen(attvalue);
 
8267
            if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
 
8268
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
 
8269
                xmlURIPtr uri;
 
8270
 
 
8271
                if (*URL != 0) {
 
8272
                    uri = xmlParseURI((const char *) URL);
 
8273
                    if (uri == NULL) {
 
8274
                        xmlWarningMsg(ctxt, XML_WAR_NS_URI,
 
8275
                                      "xmlns: %s not a valid URI\n",
 
8276
                                      URL, NULL);
 
8277
                    } else {
 
8278
                        if (uri->scheme == NULL) {
 
8279
                            xmlWarningMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
 
8280
                                   "xmlns: URI %s is not absolute\n",
 
8281
                                          URL, NULL);
 
8282
                        }
 
8283
                        xmlFreeURI(uri);
 
8284
                    }
 
8285
                }
 
8286
                /*
 
8287
                 * check that it's not a defined namespace
 
8288
                 */
 
8289
                for (j = 1;j <= nbNs;j++)
 
8290
                    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
 
8291
                        break;
 
8292
                if (j <= nbNs)
 
8293
                    xmlErrAttributeDup(ctxt, NULL, attname);
 
8294
                else
 
8295
                    if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
 
8296
                if (alloc != 0) xmlFree(attvalue);
 
8297
                SKIP_BLANKS;
 
8298
                continue;
 
8299
            }
 
8300
            if (aprefix == ctxt->str_xmlns) {
 
8301
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
 
8302
                xmlURIPtr uri;
 
8303
 
 
8304
                if (attname == ctxt->str_xml) {
 
8305
                    if (URL != ctxt->str_xml_ns) {
 
8306
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
8307
                                 "xml namespace prefix mapped to wrong URI\n",
 
8308
                                 NULL, NULL, NULL);
 
8309
                    }
 
8310
                    /*
 
8311
                     * Do not keep a namespace definition node
 
8312
                     */
 
8313
                    if (alloc != 0) xmlFree(attvalue);
 
8314
                    SKIP_BLANKS;
 
8315
                    continue;
 
8316
                }
 
8317
                uri = xmlParseURI((const char *) URL);
 
8318
                if (uri == NULL) {
 
8319
                    xmlWarningMsg(ctxt, XML_WAR_NS_URI,
 
8320
                         "xmlns:%s: '%s' is not a valid URI\n",
 
8321
                                       attname, URL);
 
8322
                } else {
 
8323
                    if ((ctxt->pedantic) && (uri->scheme == NULL)) {
 
8324
                        xmlWarningMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
 
8325
                                      "xmlns:%s: URI %s is not absolute\n",
 
8326
                                      attname, URL);
 
8327
                    }
 
8328
                    xmlFreeURI(uri);
 
8329
                }
 
8330
 
 
8331
                /*
 
8332
                 * check that it's not a defined namespace
 
8333
                 */
 
8334
                for (j = 1;j <= nbNs;j++)
 
8335
                    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
 
8336
                        break;
 
8337
                if (j <= nbNs)
 
8338
                    xmlErrAttributeDup(ctxt, aprefix, attname);
 
8339
                else
 
8340
                    if (nsPush(ctxt, attname, URL) > 0) nbNs++;
 
8341
                if (alloc != 0) xmlFree(attvalue);
 
8342
                SKIP_BLANKS;
 
8343
                if (ctxt->input->base != base) goto base_changed;
 
8344
                continue;
 
8345
            }
 
8346
 
 
8347
            /*
 
8348
             * Add the pair to atts
 
8349
             */
 
8350
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
 
8351
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
 
8352
                    if (attvalue[len] == 0)
 
8353
                        xmlFree(attvalue);
 
8354
                    goto failed;
 
8355
                }
 
8356
                maxatts = ctxt->maxatts;
 
8357
                atts = ctxt->atts;
 
8358
            }
 
8359
            ctxt->attallocs[nratts++] = alloc;
 
8360
            atts[nbatts++] = attname;
 
8361
            atts[nbatts++] = aprefix;
 
8362
            atts[nbatts++] = NULL; /* the URI will be fetched later */
 
8363
            atts[nbatts++] = attvalue;
 
8364
            attvalue += len;
 
8365
            atts[nbatts++] = attvalue;
 
8366
            /*
 
8367
             * tag if some deallocation is needed
 
8368
             */
 
8369
            if (alloc != 0) attval = 1;
 
8370
        } else {
 
8371
            if ((attvalue != NULL) && (attvalue[len] == 0))
 
8372
                xmlFree(attvalue);
 
8373
        }
 
8374
 
 
8375
failed:     
 
8376
 
 
8377
        GROW
 
8378
        if (ctxt->input->base != base) goto base_changed;
 
8379
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 
8380
            break;
 
8381
        if (!IS_BLANK_CH(RAW)) {
 
8382
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
8383
                           "attributes construct error\n");
 
8384
            break;
 
8385
        }
 
8386
        SKIP_BLANKS;
 
8387
        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
 
8388
            (attname == NULL) && (attvalue == NULL)) {
 
8389
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8390
                 "xmlParseStartTag: problem parsing attributes\n");
 
8391
            break;
 
8392
        }
 
8393
        GROW;
 
8394
        if (ctxt->input->base != base) goto base_changed;
 
8395
    }
 
8396
 
 
8397
    /*
 
8398
     * The attributes defaulting
 
8399
     */
 
8400
    if (ctxt->attsDefault != NULL) {
 
8401
        xmlDefAttrsPtr defaults;
 
8402
 
 
8403
        defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
 
8404
        if (defaults != NULL) {
 
8405
            for (i = 0;i < defaults->nbAttrs;i++) {
 
8406
                attname = defaults->values[4 * i];
 
8407
                aprefix = defaults->values[4 * i + 1];
 
8408
 
 
8409
                /*
 
8410
                 * special work for namespaces defaulted defs
 
8411
                 */
 
8412
                if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
 
8413
                    /*
 
8414
                     * check that it's not a defined namespace
 
8415
                     */
 
8416
                    for (j = 1;j <= nbNs;j++)
 
8417
                        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
 
8418
                            break;
 
8419
                    if (j <= nbNs) continue;
 
8420
 
 
8421
                    nsname = xmlGetNamespace(ctxt, NULL);
 
8422
                    if (nsname != defaults->values[4 * i + 2]) {
 
8423
                        if (nsPush(ctxt, NULL,
 
8424
                                   defaults->values[4 * i + 2]) > 0)
 
8425
                            nbNs++;
 
8426
                    }
 
8427
                } else if (aprefix == ctxt->str_xmlns) {
 
8428
                    /*
 
8429
                     * check that it's not a defined namespace
 
8430
                     */
 
8431
                    for (j = 1;j <= nbNs;j++)
 
8432
                        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
 
8433
                            break;
 
8434
                    if (j <= nbNs) continue;
 
8435
 
 
8436
                    nsname = xmlGetNamespace(ctxt, attname);
 
8437
                    if (nsname != defaults->values[2]) {
 
8438
                        if (nsPush(ctxt, attname,
 
8439
                                   defaults->values[4 * i + 2]) > 0)
 
8440
                            nbNs++;
 
8441
                    }
 
8442
                } else {
 
8443
                    /*
 
8444
                     * check that it's not a defined attribute
 
8445
                     */
 
8446
                    for (j = 0;j < nbatts;j+=5) {
 
8447
                        if ((attname == atts[j]) && (aprefix == atts[j+1]))
 
8448
                            break;
 
8449
                    }
 
8450
                    if (j < nbatts) continue;
 
8451
 
 
8452
                    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
 
8453
                        if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
 
8454
                            return(NULL);
 
8455
                        }
 
8456
                        maxatts = ctxt->maxatts;
 
8457
                        atts = ctxt->atts;
 
8458
                    }
 
8459
                    atts[nbatts++] = attname;
 
8460
                    atts[nbatts++] = aprefix;
 
8461
                    if (aprefix == NULL)
 
8462
                        atts[nbatts++] = NULL;
 
8463
                    else
 
8464
                        atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
 
8465
                    atts[nbatts++] = defaults->values[4 * i + 2];
 
8466
                    atts[nbatts++] = defaults->values[4 * i + 3];
 
8467
                    nbdef++;
 
8468
                }
 
8469
            }
 
8470
        }
 
8471
    }
 
8472
 
 
8473
    /*
 
8474
     * The attributes checkings
 
8475
     */
 
8476
    for (i = 0; i < nbatts;i += 5) {
 
8477
        /*
 
8478
        * The default namespace does not apply to attribute names.
 
8479
        */
 
8480
        if (atts[i + 1] != NULL) {
 
8481
            nsname = xmlGetNamespace(ctxt, atts[i + 1]);
 
8482
            if (nsname == NULL) {
 
8483
                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 
8484
                    "Namespace prefix %s for %s on %s is not defined\n",
 
8485
                    atts[i + 1], atts[i], localname);
 
8486
            }
 
8487
            atts[i + 2] = nsname;
 
8488
        } else
 
8489
            nsname = NULL;
 
8490
        /*
 
8491
         * [ WFC: Unique Att Spec ]
 
8492
         * No attribute name may appear more than once in the same
 
8493
         * start-tag or empty-element tag. 
 
8494
         * As extended by the Namespace in XML REC.
 
8495
         */
 
8496
        for (j = 0; j < i;j += 5) {
 
8497
            if (atts[i] == atts[j]) {
 
8498
                if (atts[i+1] == atts[j+1]) {
 
8499
                    xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
 
8500
                    break;
 
8501
                }
 
8502
                if ((nsname != NULL) && (atts[j + 2] == nsname)) {
 
8503
                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
 
8504
                             "Namespaced Attribute %s in '%s' redefined\n",
 
8505
                             atts[i], nsname, NULL);
 
8506
                    break;
 
8507
                }
 
8508
            }
 
8509
        }
 
8510
    }
 
8511
 
 
8512
    nsname = xmlGetNamespace(ctxt, prefix);
 
8513
    if ((prefix != NULL) && (nsname == NULL)) {
 
8514
        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 
8515
                 "Namespace prefix %s on %s is not defined\n",
 
8516
                 prefix, localname, NULL);
 
8517
    }
 
8518
    *pref = prefix;
 
8519
    *URI = nsname;
 
8520
 
 
8521
    /*
 
8522
     * SAX: Start of Element !
 
8523
     */
 
8524
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
 
8525
        (!ctxt->disableSAX)) {
 
8526
        if (nbNs > 0)
 
8527
            ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
 
8528
                          nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
 
8529
                          nbatts / 5, nbdef, atts);
 
8530
        else
 
8531
            ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
 
8532
                          nsname, 0, NULL, nbatts / 5, nbdef, atts);
 
8533
    }
 
8534
 
 
8535
    /*
 
8536
     * Free up attribute allocated strings if needed
 
8537
     */
 
8538
    if (attval != 0) {
 
8539
        for (i = 3,j = 0; j < nratts;i += 5,j++)
 
8540
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
 
8541
                xmlFree((xmlChar *) atts[i]);
 
8542
    }
 
8543
 
 
8544
    return(localname);
 
8545
 
 
8546
base_changed:
 
8547
    /*
 
8548
     * the attribute strings are valid iif the base didn't changed
 
8549
     */
 
8550
    if (attval != 0) {
 
8551
        for (i = 3,j = 0; j < nratts;i += 5,j++)
 
8552
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
 
8553
                xmlFree((xmlChar *) atts[i]);
 
8554
    }
 
8555
    ctxt->input->cur = ctxt->input->base + cur;
 
8556
    ctxt->input->line = oldline;
 
8557
    ctxt->input->col = oldcol;
 
8558
    if (ctxt->wellFormed == 1) {
 
8559
        goto reparse;
 
8560
    }
 
8561
    return(NULL);
 
8562
}
 
8563
 
 
8564
/**
 
8565
 * xmlParseEndTag2:
 
8566
 * @ctxt:  an XML parser context
 
8567
 * @line:  line of the start tag
 
8568
 * @nsNr:  number of namespaces on the start tag
 
8569
 *
 
8570
 * parse an end of tag
 
8571
 *
 
8572
 * [42] ETag ::= '</' Name S? '>'
 
8573
 *
 
8574
 * With namespace
 
8575
 *
 
8576
 * [NS 9] ETag ::= '</' QName S? '>'
 
8577
 */
 
8578
 
 
8579
static void
 
8580
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
 
8581
                const xmlChar *URI, int line, int nsNr, int tlen) {
 
8582
    const xmlChar *name;
 
8583
 
 
8584
    GROW;
 
8585
    if ((RAW != '<') || (NXT(1) != '/')) {
 
8586
        xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
 
8587
        return;
 
8588
    }
 
8589
    SKIP(2);
 
8590
 
 
8591
    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
 
8592
        if (ctxt->input->cur[tlen] == '>') {
 
8593
            ctxt->input->cur += tlen + 1;
 
8594
            goto done;
 
8595
        }
 
8596
        ctxt->input->cur += tlen;
 
8597
        name = (xmlChar*)1;
 
8598
    } else {
 
8599
        if (prefix == NULL)
 
8600
            name = xmlParseNameAndCompare(ctxt, ctxt->name);
 
8601
        else
 
8602
            name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
 
8603
    }
 
8604
 
 
8605
    /*
 
8606
     * We should definitely be at the ending "S? '>'" part
 
8607
     */
 
8608
    GROW;
 
8609
    SKIP_BLANKS;
 
8610
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 
8611
        xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
8612
    } else
 
8613
        NEXT1;
 
8614
 
 
8615
    /*
 
8616
     * [ WFC: Element Type Match ]
 
8617
     * The Name in an element's end-tag must match the element type in the
 
8618
     * start-tag. 
 
8619
     *
 
8620
     */
 
8621
    if (name != (xmlChar*)1) {
 
8622
        if (name == NULL) name = BAD_CAST "unparseable";
 
8623
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
 
8624
                     "Opening and ending tag mismatch: %s line %d and %s\n",
 
8625
                                ctxt->name, line, name);
 
8626
    }
 
8627
 
 
8628
    /*
 
8629
     * SAX: End of Tag
 
8630
     */
 
8631
done:
 
8632
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
 
8633
        (!ctxt->disableSAX))
 
8634
        ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
 
8635
 
 
8636
    spacePop(ctxt);
 
8637
    if (nsNr != 0)
 
8638
        nsPop(ctxt, nsNr);
 
8639
    return;
 
8640
}
 
8641
 
 
8642
/**
 
8643
 * xmlParseCDSect:
 
8644
 * @ctxt:  an XML parser context
 
8645
 * 
 
8646
 * Parse escaped pure raw content.
 
8647
 *
 
8648
 * [18] CDSect ::= CDStart CData CDEnd
 
8649
 *
 
8650
 * [19] CDStart ::= '<![CDATA['
 
8651
 *
 
8652
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
 
8653
 *
 
8654
 * [21] CDEnd ::= ']]>'
 
8655
 */
 
8656
void
 
8657
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
 
8658
    xmlChar *buf = NULL;
 
8659
    int len = 0;
 
8660
    int size = XML_PARSER_BUFFER_SIZE;
 
8661
    int r, rl;
 
8662
    int s, sl;
 
8663
    int cur, l;
 
8664
    int count = 0;
 
8665
 
 
8666
    /* Check 2.6.0 was NXT(0) not RAW */
 
8667
    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
 
8668
        SKIP(9);
 
8669
    } else
 
8670
        return;
 
8671
 
 
8672
    ctxt->instate = XML_PARSER_CDATA_SECTION;
 
8673
    r = CUR_CHAR(rl);
 
8674
    if (!IS_CHAR(r)) {
 
8675
        xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
 
8676
        ctxt->instate = XML_PARSER_CONTENT;
 
8677
        return;
 
8678
    }
 
8679
    NEXTL(rl);
 
8680
    s = CUR_CHAR(sl);
 
8681
    if (!IS_CHAR(s)) {
 
8682
        xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
 
8683
        ctxt->instate = XML_PARSER_CONTENT;
 
8684
        return;
 
8685
    }
 
8686
    NEXTL(sl);
 
8687
    cur = CUR_CHAR(l);
 
8688
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
8689
    if (buf == NULL) {
 
8690
        xmlErrMemory(ctxt, NULL);
 
8691
        return;
 
8692
    }
 
8693
    while (IS_CHAR(cur) &&
 
8694
           ((r != ']') || (s != ']') || (cur != '>'))) {
 
8695
        if (len + 5 >= size) {
 
8696
            xmlChar *tmp;
 
8697
 
 
8698
            size *= 2;
 
8699
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
8700
            if (tmp == NULL) {
 
8701
                xmlFree(buf);
 
8702
                xmlErrMemory(ctxt, NULL);
 
8703
                return;
 
8704
            }
 
8705
            buf = tmp;
 
8706
        }
 
8707
        COPY_BUF(rl,buf,len,r);
 
8708
        r = s;
 
8709
        rl = sl;
 
8710
        s = cur;
 
8711
        sl = l;
 
8712
        count++;
 
8713
        if (count > 50) {
 
8714
            GROW;
 
8715
            count = 0;
 
8716
        }
 
8717
        NEXTL(l);
 
8718
        cur = CUR_CHAR(l);
 
8719
    }
 
8720
    buf[len] = 0;
 
8721
    ctxt->instate = XML_PARSER_CONTENT;
 
8722
    if (cur != '>') {
 
8723
        xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
 
8724
                             "CData section not finished\n%.50s\n", buf);
 
8725
        xmlFree(buf);
 
8726
        return;
 
8727
    }
 
8728
    NEXTL(l);
 
8729
 
 
8730
    /*
 
8731
     * OK the buffer is to be consumed as cdata.
 
8732
     */
 
8733
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
8734
        if (ctxt->sax->cdataBlock != NULL)
 
8735
            ctxt->sax->cdataBlock(ctxt->userData, buf, len);
 
8736
        else if (ctxt->sax->characters != NULL)
 
8737
            ctxt->sax->characters(ctxt->userData, buf, len);
 
8738
    }
 
8739
    xmlFree(buf);
 
8740
}
 
8741
 
 
8742
/**
 
8743
 * xmlParseContent:
 
8744
 * @ctxt:  an XML parser context
 
8745
 *
 
8746
 * Parse a content:
 
8747
 *
 
8748
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
8749
 */
 
8750
 
 
8751
void
 
8752
xmlParseContent(xmlParserCtxtPtr ctxt) {
 
8753
    GROW;
 
8754
    while ((RAW != 0) &&
 
8755
           ((RAW != '<') || (NXT(1) != '/')) &&
 
8756
           (ctxt->instate != XML_PARSER_EOF)) {
 
8757
        const xmlChar *test = CUR_PTR;
 
8758
        unsigned int cons = ctxt->input->consumed;
 
8759
        const xmlChar *cur = ctxt->input->cur;
 
8760
 
 
8761
        /*
 
8762
         * First case : a Processing Instruction.
 
8763
         */
 
8764
        if ((*cur == '<') && (cur[1] == '?')) {
 
8765
            xmlParsePI(ctxt);
 
8766
        }
 
8767
 
 
8768
        /*
 
8769
         * Second case : a CDSection
 
8770
         */
 
8771
        /* 2.6.0 test was *cur not RAW */
 
8772
        else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
 
8773
            xmlParseCDSect(ctxt);
 
8774
        }
 
8775
 
 
8776
        /*
 
8777
         * Third case :  a comment
 
8778
         */
 
8779
        else if ((*cur == '<') && (NXT(1) == '!') &&
 
8780
                 (NXT(2) == '-') && (NXT(3) == '-')) {
 
8781
            xmlParseComment(ctxt);
 
8782
            ctxt->instate = XML_PARSER_CONTENT;
 
8783
        }
 
8784
 
 
8785
        /*
 
8786
         * Fourth case :  a sub-element.
 
8787
         */
 
8788
        else if (*cur == '<') {
 
8789
            xmlParseElement(ctxt);
 
8790
        }
 
8791
 
 
8792
        /*
 
8793
         * Fifth case : a reference. If if has not been resolved,
 
8794
         *    parsing returns it's Name, create the node 
 
8795
         */
 
8796
 
 
8797
        else if (*cur == '&') {
 
8798
            xmlParseReference(ctxt);
 
8799
        }
 
8800
 
 
8801
        /*
 
8802
         * Last case, text. Note that References are handled directly.
 
8803
         */
 
8804
        else {
 
8805
            xmlParseCharData(ctxt, 0);
 
8806
        }
 
8807
 
 
8808
        GROW;
 
8809
        /*
 
8810
         * Pop-up of finished entities.
 
8811
         */
 
8812
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
8813
            xmlPopInput(ctxt);
 
8814
        SHRINK;
 
8815
 
 
8816
        if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
 
8817
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8818
                        "detected an error in element content\n");
 
8819
            ctxt->instate = XML_PARSER_EOF;
 
8820
            break;
 
8821
        }
 
8822
    }
 
8823
}
 
8824
 
 
8825
/**
 
8826
 * xmlParseElement:
 
8827
 * @ctxt:  an XML parser context
 
8828
 *
 
8829
 * parse an XML element, this is highly recursive
 
8830
 *
 
8831
 * [39] element ::= EmptyElemTag | STag content ETag
 
8832
 *
 
8833
 * [ WFC: Element Type Match ]
 
8834
 * The Name in an element's end-tag must match the element type in the
 
8835
 * start-tag. 
 
8836
 *
 
8837
 */
 
8838
 
 
8839
void
 
8840
xmlParseElement(xmlParserCtxtPtr ctxt) {
 
8841
    const xmlChar *name;
 
8842
    const xmlChar *prefix;
 
8843
    const xmlChar *URI;
 
8844
    xmlParserNodeInfo node_info;
 
8845
    int line, tlen;
 
8846
    xmlNodePtr ret;
 
8847
    int nsNr = ctxt->nsNr;
 
8848
 
 
8849
    if ((unsigned int) ctxt->nameNr > xmlParserMaxDepth) {
 
8850
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
 
8851
              "Excessive depth in document: change xmlParserMaxDepth = %d\n",
 
8852
                          xmlParserMaxDepth);
 
8853
        ctxt->instate = XML_PARSER_EOF;
 
8854
        return;
 
8855
    }
 
8856
 
 
8857
    /* Capture start position */
 
8858
    if (ctxt->record_info) {
 
8859
        node_info.begin_pos = ctxt->input->consumed +
 
8860
                          (CUR_PTR - ctxt->input->base);
 
8861
        node_info.begin_line = ctxt->input->line;
 
8862
    }
 
8863
 
 
8864
    if (ctxt->spaceNr == 0)
 
8865
        spacePush(ctxt, -1);
 
8866
    else if (*ctxt->space == -2)
 
8867
        spacePush(ctxt, -1);
 
8868
    else
 
8869
        spacePush(ctxt, *ctxt->space);
 
8870
 
 
8871
    line = ctxt->input->line;
 
8872
#ifdef LIBXML_SAX1_ENABLED
 
8873
    if (ctxt->sax2)
 
8874
#endif /* LIBXML_SAX1_ENABLED */
 
8875
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
 
8876
#ifdef LIBXML_SAX1_ENABLED
 
8877
    else
 
8878
        name = xmlParseStartTag(ctxt);
 
8879
#endif /* LIBXML_SAX1_ENABLED */
 
8880
    if (name == NULL) {
 
8881
        spacePop(ctxt);
 
8882
        return;
 
8883
    }
 
8884
    namePush(ctxt, name);
 
8885
    ret = ctxt->node;
 
8886
 
 
8887
#ifdef LIBXML_VALID_ENABLED
 
8888
    /*
 
8889
     * [ VC: Root Element Type ]
 
8890
     * The Name in the document type declaration must match the element
 
8891
     * type of the root element. 
 
8892
     */
 
8893
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
 
8894
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
 
8895
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
 
8896
#endif /* LIBXML_VALID_ENABLED */
 
8897
 
 
8898
    /*
 
8899
     * Check for an Empty Element.
 
8900
     */
 
8901
    if ((RAW == '/') && (NXT(1) == '>')) {
 
8902
        SKIP(2);
 
8903
        if (ctxt->sax2) {
 
8904
            if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
 
8905
                (!ctxt->disableSAX))
 
8906
                ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
 
8907
#ifdef LIBXML_SAX1_ENABLED
 
8908
        } else {
 
8909
            if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
 
8910
                (!ctxt->disableSAX))
 
8911
                ctxt->sax->endElement(ctxt->userData, name);
 
8912
#endif /* LIBXML_SAX1_ENABLED */
 
8913
        }
 
8914
        namePop(ctxt);
 
8915
        spacePop(ctxt);
 
8916
        if (nsNr != ctxt->nsNr)
 
8917
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
8918
        if ( ret != NULL && ctxt->record_info ) {
 
8919
           node_info.end_pos = ctxt->input->consumed +
 
8920
                              (CUR_PTR - ctxt->input->base);
 
8921
           node_info.end_line = ctxt->input->line;
 
8922
           node_info.node = ret;
 
8923
           xmlParserAddNodeInfo(ctxt, &node_info);
 
8924
        }
 
8925
        return;
 
8926
    }
 
8927
    if (RAW == '>') {
 
8928
        NEXT1;
 
8929
    } else {
 
8930
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
 
8931
                     "Couldn't find end of Start Tag %s line %d\n",
 
8932
                                name, line, NULL);
 
8933
 
 
8934
        /*
 
8935
         * end of parsing of this node.
 
8936
         */
 
8937
        nodePop(ctxt);
 
8938
        namePop(ctxt);
 
8939
        spacePop(ctxt);
 
8940
        if (nsNr != ctxt->nsNr)
 
8941
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
8942
 
 
8943
        /*
 
8944
         * Capture end position and add node
 
8945
         */
 
8946
        if ( ret != NULL && ctxt->record_info ) {
 
8947
           node_info.end_pos = ctxt->input->consumed +
 
8948
                              (CUR_PTR - ctxt->input->base);
 
8949
           node_info.end_line = ctxt->input->line;
 
8950
           node_info.node = ret;
 
8951
           xmlParserAddNodeInfo(ctxt, &node_info);
 
8952
        }
 
8953
        return;
 
8954
    }
 
8955
 
 
8956
    /*
 
8957
     * Parse the content of the element:
 
8958
     */
 
8959
    xmlParseContent(ctxt);
 
8960
    if (!IS_BYTE_CHAR(RAW)) {
 
8961
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
 
8962
         "Premature end of data in tag %s line %d\n",
 
8963
                                name, line, NULL);
 
8964
 
 
8965
        /*
 
8966
         * end of parsing of this node.
 
8967
         */
 
8968
        nodePop(ctxt);
 
8969
        namePop(ctxt);
 
8970
        spacePop(ctxt);
 
8971
        if (nsNr != ctxt->nsNr)
 
8972
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
8973
        return;
 
8974
    }
 
8975
 
 
8976
    /*
 
8977
     * parse the end of tag: '</' should be here.
 
8978
     */
 
8979
    if (ctxt->sax2) {
 
8980
        xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
 
8981
        namePop(ctxt);
 
8982
    }
 
8983
#ifdef LIBXML_SAX1_ENABLED
 
8984
      else
 
8985
        xmlParseEndTag1(ctxt, line);
 
8986
#endif /* LIBXML_SAX1_ENABLED */
 
8987
 
 
8988
    /*
 
8989
     * Capture end position and add node
 
8990
     */
 
8991
    if ( ret != NULL && ctxt->record_info ) {
 
8992
       node_info.end_pos = ctxt->input->consumed +
 
8993
                          (CUR_PTR - ctxt->input->base);
 
8994
       node_info.end_line = ctxt->input->line;
 
8995
       node_info.node = ret;
 
8996
       xmlParserAddNodeInfo(ctxt, &node_info);
 
8997
    }
 
8998
}
 
8999
 
 
9000
/**
 
9001
 * xmlParseVersionNum:
 
9002
 * @ctxt:  an XML parser context
 
9003
 *
 
9004
 * parse the XML version value.
 
9005
 *
 
9006
 * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
 
9007
 *
 
9008
 * Returns the string giving the XML version number, or NULL
 
9009
 */
 
9010
xmlChar *
 
9011
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
 
9012
    xmlChar *buf = NULL;
 
9013
    int len = 0;
 
9014
    int size = 10;
 
9015
    xmlChar cur;
 
9016
 
 
9017
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
9018
    if (buf == NULL) {
 
9019
        xmlErrMemory(ctxt, NULL);
 
9020
        return(NULL);
 
9021
    }
 
9022
    cur = CUR;
 
9023
    while (((cur >= 'a') && (cur <= 'z')) ||
 
9024
           ((cur >= 'A') && (cur <= 'Z')) ||
 
9025
           ((cur >= '0') && (cur <= '9')) ||
 
9026
           (cur == '_') || (cur == '.') ||
 
9027
           (cur == ':') || (cur == '-')) {
 
9028
        if (len + 1 >= size) {
 
9029
            xmlChar *tmp;
 
9030
 
 
9031
            size *= 2;
 
9032
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
9033
            if (tmp == NULL) {
 
9034
                xmlFree(buf);
 
9035
                xmlErrMemory(ctxt, NULL);
 
9036
                return(NULL);
 
9037
            }
 
9038
            buf = tmp;
 
9039
        }
 
9040
        buf[len++] = cur;
 
9041
        NEXT;
 
9042
        cur=CUR;
 
9043
    }
 
9044
    buf[len] = 0;
 
9045
    return(buf);
 
9046
}
 
9047
 
 
9048
/**
 
9049
 * xmlParseVersionInfo:
 
9050
 * @ctxt:  an XML parser context
 
9051
 *
 
9052
 * parse the XML version.
 
9053
 *
 
9054
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
 
9055
 *
 
9056
 * [25] Eq ::= S? '=' S?
 
9057
 *
 
9058
 * Returns the version string, e.g. "1.0"
 
9059
 */
 
9060
 
 
9061
xmlChar *
 
9062
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
 
9063
    xmlChar *version = NULL;
 
9064
 
 
9065
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
 
9066
        SKIP(7);
 
9067
        SKIP_BLANKS;
 
9068
        if (RAW != '=') {
 
9069
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
9070
            return(NULL);
 
9071
        }
 
9072
        NEXT;
 
9073
        SKIP_BLANKS;
 
9074
        if (RAW == '"') {
 
9075
            NEXT;
 
9076
            version = xmlParseVersionNum(ctxt);
 
9077
            if (RAW != '"') {
 
9078
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
9079
            } else
 
9080
                NEXT;
 
9081
        } else if (RAW == '\''){
 
9082
            NEXT;
 
9083
            version = xmlParseVersionNum(ctxt);
 
9084
            if (RAW != '\'') {
 
9085
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
9086
            } else
 
9087
                NEXT;
 
9088
        } else {
 
9089
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
9090
        }
 
9091
    }
 
9092
    return(version);
 
9093
}
 
9094
 
 
9095
/**
 
9096
 * xmlParseEncName:
 
9097
 * @ctxt:  an XML parser context
 
9098
 *
 
9099
 * parse the XML encoding name
 
9100
 *
 
9101
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
 
9102
 *
 
9103
 * Returns the encoding name value or NULL
 
9104
 */
 
9105
xmlChar *
 
9106
xmlParseEncName(xmlParserCtxtPtr ctxt) {
 
9107
    xmlChar *buf = NULL;
 
9108
    int len = 0;
 
9109
    int size = 10;
 
9110
    xmlChar cur;
 
9111
 
 
9112
    cur = CUR;
 
9113
    if (((cur >= 'a') && (cur <= 'z')) ||
 
9114
        ((cur >= 'A') && (cur <= 'Z'))) {
 
9115
        buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
9116
        if (buf == NULL) {
 
9117
            xmlErrMemory(ctxt, NULL);
 
9118
            return(NULL);
 
9119
        }
 
9120
        
 
9121
        buf[len++] = cur;
 
9122
        NEXT;
 
9123
        cur = CUR;
 
9124
        while (((cur >= 'a') && (cur <= 'z')) ||
 
9125
               ((cur >= 'A') && (cur <= 'Z')) ||
 
9126
               ((cur >= '0') && (cur <= '9')) ||
 
9127
               (cur == '.') || (cur == '_') ||
 
9128
               (cur == '-')) {
 
9129
            if (len + 1 >= size) {
 
9130
                xmlChar *tmp;
 
9131
 
 
9132
                size *= 2;
 
9133
                tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
9134
                if (tmp == NULL) {
 
9135
                    xmlErrMemory(ctxt, NULL);
 
9136
                    xmlFree(buf);
 
9137
                    return(NULL);
 
9138
                }
 
9139
                buf = tmp;
 
9140
            }
 
9141
            buf[len++] = cur;
 
9142
            NEXT;
 
9143
            cur = CUR;
 
9144
            if (cur == 0) {
 
9145
                SHRINK;
 
9146
                GROW;
 
9147
                cur = CUR;
 
9148
            }
 
9149
        }
 
9150
        buf[len] = 0;
 
9151
    } else {
 
9152
        xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
 
9153
    }
 
9154
    return(buf);
 
9155
}
 
9156
 
 
9157
/**
 
9158
 * xmlParseEncodingDecl:
 
9159
 * @ctxt:  an XML parser context
 
9160
 * 
 
9161
 * parse the XML encoding declaration
 
9162
 *
 
9163
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
 
9164
 *
 
9165
 * this setups the conversion filters.
 
9166
 *
 
9167
 * Returns the encoding value or NULL
 
9168
 */
 
9169
 
 
9170
const xmlChar *
 
9171
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
 
9172
    xmlChar *encoding = NULL;
 
9173
 
 
9174
    SKIP_BLANKS;
 
9175
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
 
9176
        SKIP(8);
 
9177
        SKIP_BLANKS;
 
9178
        if (RAW != '=') {
 
9179
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
9180
            return(NULL);
 
9181
        }
 
9182
        NEXT;
 
9183
        SKIP_BLANKS;
 
9184
        if (RAW == '"') {
 
9185
            NEXT;
 
9186
            encoding = xmlParseEncName(ctxt);
 
9187
            if (RAW != '"') {
 
9188
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
9189
            } else
 
9190
                NEXT;
 
9191
        } else if (RAW == '\''){
 
9192
            NEXT;
 
9193
            encoding = xmlParseEncName(ctxt);
 
9194
            if (RAW != '\'') {
 
9195
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
9196
            } else
 
9197
                NEXT;
 
9198
        } else {
 
9199
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
9200
        }
 
9201
        /*
 
9202
         * UTF-16 encoding stwich has already taken place at this stage,
 
9203
         * more over the little-endian/big-endian selection is already done
 
9204
         */
 
9205
        if ((encoding != NULL) &&
 
9206
            ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
 
9207
             (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
 
9208
            if (ctxt->encoding != NULL)
 
9209
                xmlFree((xmlChar *) ctxt->encoding);
 
9210
            ctxt->encoding = encoding;
 
9211
        }
 
9212
        /*
 
9213
         * UTF-8 encoding is handled natively
 
9214
         */
 
9215
        else if ((encoding != NULL) &&
 
9216
            ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
 
9217
             (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
 
9218
            if (ctxt->encoding != NULL)
 
9219
                xmlFree((xmlChar *) ctxt->encoding);
 
9220
            ctxt->encoding = encoding;
 
9221
        }
 
9222
        else if (encoding != NULL) {
 
9223
            xmlCharEncodingHandlerPtr handler;
 
9224
 
 
9225
            if (ctxt->input->encoding != NULL)
 
9226
                xmlFree((xmlChar *) ctxt->input->encoding);
 
9227
            ctxt->input->encoding = encoding;
 
9228
 
 
9229
            handler = xmlFindCharEncodingHandler((const char *) encoding);
 
9230
            if (handler != NULL) {
 
9231
                xmlSwitchToEncoding(ctxt, handler);
 
9232
            } else {
 
9233
                xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 
9234
                        "Unsupported encoding %s\n", encoding);
 
9235
                return(NULL);
 
9236
            }
 
9237
        }
 
9238
    }
 
9239
    return(encoding);
 
9240
}
 
9241
 
 
9242
/**
 
9243
 * xmlParseSDDecl:
 
9244
 * @ctxt:  an XML parser context
 
9245
 *
 
9246
 * parse the XML standalone declaration
 
9247
 *
 
9248
 * [32] SDDecl ::= S 'standalone' Eq
 
9249
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"')) 
 
9250
 *
 
9251
 * [ VC: Standalone Document Declaration ]
 
9252
 * TODO The standalone document declaration must have the value "no"
 
9253
 * if any external markup declarations contain declarations of:
 
9254
 *  - attributes with default values, if elements to which these
 
9255
 *    attributes apply appear in the document without specifications
 
9256
 *    of values for these attributes, or
 
9257
 *  - entities (other than amp, lt, gt, apos, quot), if references
 
9258
 *    to those entities appear in the document, or
 
9259
 *  - attributes with values subject to normalization, where the
 
9260
 *    attribute appears in the document with a value which will change
 
9261
 *    as a result of normalization, or
 
9262
 *  - element types with element content, if white space occurs directly
 
9263
 *    within any instance of those types.
 
9264
 *
 
9265
 * Returns:
 
9266
 *   1 if standalone="yes"
 
9267
 *   0 if standalone="no"
 
9268
 *  -2 if standalone attribute is missing or invalid
 
9269
 *        (A standalone value of -2 means that the XML declaration was found,
 
9270
 *         but no value was specified for the standalone attribute).
 
9271
 */
 
9272
 
 
9273
int
 
9274
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
 
9275
    int standalone = -2;
 
9276
 
 
9277
    SKIP_BLANKS;
 
9278
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
 
9279
        SKIP(10);
 
9280
        SKIP_BLANKS;
 
9281
        if (RAW != '=') {
 
9282
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
9283
            return(standalone);
 
9284
        }
 
9285
        NEXT;
 
9286
        SKIP_BLANKS;
 
9287
        if (RAW == '\''){
 
9288
            NEXT;
 
9289
            if ((RAW == 'n') && (NXT(1) == 'o')) {
 
9290
                standalone = 0;
 
9291
                SKIP(2);
 
9292
            } else if ((RAW == 'y') && (NXT(1) == 'e') &&
 
9293
                       (NXT(2) == 's')) {
 
9294
                standalone = 1;
 
9295
                SKIP(3);
 
9296
            } else {
 
9297
                xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
 
9298
            }
 
9299
            if (RAW != '\'') {
 
9300
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
9301
            } else
 
9302
                NEXT;
 
9303
        } else if (RAW == '"'){
 
9304
            NEXT;
 
9305
            if ((RAW == 'n') && (NXT(1) == 'o')) {
 
9306
                standalone = 0;
 
9307
                SKIP(2);
 
9308
            } else if ((RAW == 'y') && (NXT(1) == 'e') &&
 
9309
                       (NXT(2) == 's')) {
 
9310
                standalone = 1;
 
9311
                SKIP(3);
 
9312
            } else {
 
9313
                xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
 
9314
            }
 
9315
            if (RAW != '"') {
 
9316
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
9317
            } else
 
9318
                NEXT;
 
9319
        } else {
 
9320
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
9321
        }
 
9322
    }
 
9323
    return(standalone);
 
9324
}
 
9325
 
 
9326
/**
 
9327
 * xmlParseXMLDecl:
 
9328
 * @ctxt:  an XML parser context
 
9329
 * 
 
9330
 * parse an XML declaration header
 
9331
 *
 
9332
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
 
9333
 */
 
9334
 
 
9335
void
 
9336
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
 
9337
    xmlChar *version;
 
9338
 
 
9339
    /*
 
9340
     * This value for standalone indicates that the document has an
 
9341
     * XML declaration but it does not have a standalone attribute.
 
9342
     * It will be overwritten later if a standalone attribute is found.
 
9343
     */
 
9344
    ctxt->input->standalone = -2;
 
9345
 
 
9346
    /*
 
9347
     * We know that '<?xml' is here.
 
9348
     */
 
9349
    SKIP(5);
 
9350
 
 
9351
    if (!IS_BLANK_CH(RAW)) {
 
9352
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
9353
                       "Blank needed after '<?xml'\n");
 
9354
    }
 
9355
    SKIP_BLANKS;
 
9356
 
 
9357
    /*
 
9358
     * We must have the VersionInfo here.
 
9359
     */
 
9360
    version = xmlParseVersionInfo(ctxt);
 
9361
    if (version == NULL) {
 
9362
        xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
 
9363
    } else {
 
9364
        if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
 
9365
            /*
 
9366
             * TODO: Blueberry should be detected here
 
9367
             */
 
9368
            xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
 
9369
                          "Unsupported version '%s'\n",
 
9370
                          version, NULL);
 
9371
        }
 
9372
        if (ctxt->version != NULL)
 
9373
            xmlFree((void *) ctxt->version);
 
9374
        ctxt->version = version;
 
9375
    }
 
9376
 
 
9377
    /*
 
9378
     * We may have the encoding declaration
 
9379
     */
 
9380
    if (!IS_BLANK_CH(RAW)) {
 
9381
        if ((RAW == '?') && (NXT(1) == '>')) {
 
9382
            SKIP(2);
 
9383
            return;
 
9384
        }
 
9385
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
 
9386
    }
 
9387
    xmlParseEncodingDecl(ctxt);
 
9388
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
9389
        /*
 
9390
         * The XML REC instructs us to stop parsing right here
 
9391
         */
 
9392
        return;
 
9393
    }
 
9394
 
 
9395
    /*
 
9396
     * We may have the standalone status.
 
9397
     */
 
9398
    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
 
9399
        if ((RAW == '?') && (NXT(1) == '>')) {
 
9400
            SKIP(2);
 
9401
            return;
 
9402
        }
 
9403
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
 
9404
    }
 
9405
    SKIP_BLANKS;
 
9406
    ctxt->input->standalone = xmlParseSDDecl(ctxt);
 
9407
 
 
9408
    SKIP_BLANKS;
 
9409
    if ((RAW == '?') && (NXT(1) == '>')) {
 
9410
        SKIP(2);
 
9411
    } else if (RAW == '>') {
 
9412
        /* Deprecated old WD ... */
 
9413
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
9414
        NEXT;
 
9415
    } else {
 
9416
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
9417
        MOVETO_ENDTAG(CUR_PTR);
 
9418
        NEXT;
 
9419
    }
 
9420
}
 
9421
 
 
9422
/**
 
9423
 * xmlParseMisc:
 
9424
 * @ctxt:  an XML parser context
 
9425
 * 
 
9426
 * parse an XML Misc* optional field.
 
9427
 *
 
9428
 * [27] Misc ::= Comment | PI |  S
 
9429
 */
 
9430
 
 
9431
void
 
9432
xmlParseMisc(xmlParserCtxtPtr ctxt) {
 
9433
    while (((RAW == '<') && (NXT(1) == '?')) ||
 
9434
           (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
 
9435
           IS_BLANK_CH(CUR)) {
 
9436
        if ((RAW == '<') && (NXT(1) == '?')) {
 
9437
            xmlParsePI(ctxt);
 
9438
        } else if (IS_BLANK_CH(CUR)) {
 
9439
            NEXT;
 
9440
        } else
 
9441
            xmlParseComment(ctxt);
 
9442
    }
 
9443
}
 
9444
 
 
9445
/**
 
9446
 * xmlParseDocument:
 
9447
 * @ctxt:  an XML parser context
 
9448
 * 
 
9449
 * parse an XML document (and build a tree if using the standard SAX
 
9450
 * interface).
 
9451
 *
 
9452
 * [1] document ::= prolog element Misc*
 
9453
 *
 
9454
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
 
9455
 *
 
9456
 * Returns 0, -1 in case of error. the parser context is augmented
 
9457
 *                as a result of the parsing.
 
9458
 */
 
9459
 
 
9460
int
 
9461
xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
9462
    xmlChar start[4];
 
9463
    xmlCharEncoding enc;
 
9464
 
 
9465
    xmlInitParser();
 
9466
 
 
9467
    if ((ctxt == NULL) || (ctxt->input == NULL))
 
9468
        return(-1);
 
9469
 
 
9470
    GROW;
 
9471
 
 
9472
    /*
 
9473
     * SAX: detecting the level.
 
9474
     */
 
9475
    xmlDetectSAX2(ctxt);
 
9476
 
 
9477
    /*
 
9478
     * SAX: beginning of the document processing.
 
9479
     */
 
9480
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
9481
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
9482
 
 
9483
    if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) &&
 
9484
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
 
9485
        /* 
 
9486
         * Get the 4 first bytes and decode the charset
 
9487
         * if enc != XML_CHAR_ENCODING_NONE
 
9488
         * plug some encoding conversion routines.
 
9489
         */
 
9490
        start[0] = RAW;
 
9491
        start[1] = NXT(1);
 
9492
        start[2] = NXT(2);
 
9493
        start[3] = NXT(3);
 
9494
        enc = xmlDetectCharEncoding(&start[0], 4);
 
9495
        if (enc != XML_CHAR_ENCODING_NONE) {
 
9496
            xmlSwitchEncoding(ctxt, enc);
 
9497
        }
 
9498
    }
 
9499
 
 
9500
 
 
9501
    if (CUR == 0) {
 
9502
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
9503
    }
 
9504
 
 
9505
    /*
 
9506
     * Check for the XMLDecl in the Prolog.
 
9507
     */
 
9508
    GROW;
 
9509
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
9510
 
 
9511
        /*
 
9512
         * Note that we will switch encoding on the fly.
 
9513
         */
 
9514
        xmlParseXMLDecl(ctxt);
 
9515
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
9516
            /*
 
9517
             * The XML REC instructs us to stop parsing right here
 
9518
             */
 
9519
            return(-1);
 
9520
        }
 
9521
        ctxt->standalone = ctxt->input->standalone;
 
9522
        SKIP_BLANKS;
 
9523
    } else {
 
9524
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
9525
    }
 
9526
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 
9527
        ctxt->sax->startDocument(ctxt->userData);
 
9528
 
 
9529
    /*
 
9530
     * The Misc part of the Prolog
 
9531
     */
 
9532
    GROW;
 
9533
    xmlParseMisc(ctxt);
 
9534
 
 
9535
    /*
 
9536
     * Then possibly doc type declaration(s) and more Misc
 
9537
     * (doctypedecl Misc*)?
 
9538
     */
 
9539
    GROW;
 
9540
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
 
9541
 
 
9542
        ctxt->inSubset = 1;
 
9543
        xmlParseDocTypeDecl(ctxt);
 
9544
        if (RAW == '[') {
 
9545
            ctxt->instate = XML_PARSER_DTD;
 
9546
            xmlParseInternalSubset(ctxt);
 
9547
        }
 
9548
 
 
9549
        /*
 
9550
         * Create and update the external subset.
 
9551
         */
 
9552
        ctxt->inSubset = 2;
 
9553
        if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
 
9554
            (!ctxt->disableSAX))
 
9555
            ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 
9556
                                      ctxt->extSubSystem, ctxt->extSubURI);
 
9557
        ctxt->inSubset = 0;
 
9558
 
 
9559
        xmlCleanSpecialAttr(ctxt);
 
9560
 
 
9561
        ctxt->instate = XML_PARSER_PROLOG;
 
9562
        xmlParseMisc(ctxt);
 
9563
    }
 
9564
 
 
9565
    /*
 
9566
     * Time to start parsing the tree itself
 
9567
     */
 
9568
    GROW;
 
9569
    if (RAW != '<') {
 
9570
        xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
 
9571
                       "Start tag expected, '<' not found\n");
 
9572
    } else {
 
9573
        ctxt->instate = XML_PARSER_CONTENT;
 
9574
        xmlParseElement(ctxt);
 
9575
        ctxt->instate = XML_PARSER_EPILOG;
 
9576
 
 
9577
 
 
9578
        /*
 
9579
         * The Misc part at the end
 
9580
         */
 
9581
        xmlParseMisc(ctxt);
 
9582
 
 
9583
        if (RAW != 0) {
 
9584
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
9585
        }
 
9586
        ctxt->instate = XML_PARSER_EOF;
 
9587
    }
 
9588
 
 
9589
    /*
 
9590
     * SAX: end of the document processing.
 
9591
     */
 
9592
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
9593
        ctxt->sax->endDocument(ctxt->userData);
 
9594
 
 
9595
    /*
 
9596
     * Remove locally kept entity definitions if the tree was not built
 
9597
     */
 
9598
    if ((ctxt->myDoc != NULL) &&
 
9599
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
 
9600
        xmlFreeDoc(ctxt->myDoc);
 
9601
        ctxt->myDoc = NULL;
 
9602
    }
 
9603
 
 
9604
    if (! ctxt->wellFormed) {
 
9605
        ctxt->valid = 0;
 
9606
        return(-1);
 
9607
    }
 
9608
    return(0);
 
9609
}
 
9610
 
 
9611
/**
 
9612
 * xmlParseExtParsedEnt:
 
9613
 * @ctxt:  an XML parser context
 
9614
 * 
 
9615
 * parse a general parsed entity
 
9616
 * An external general parsed entity is well-formed if it matches the
 
9617
 * production labeled extParsedEnt.
 
9618
 *
 
9619
 * [78] extParsedEnt ::= TextDecl? content
 
9620
 *
 
9621
 * Returns 0, -1 in case of error. the parser context is augmented
 
9622
 *                as a result of the parsing.
 
9623
 */
 
9624
 
 
9625
int
 
9626
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
 
9627
    xmlChar start[4];
 
9628
    xmlCharEncoding enc;
 
9629
 
 
9630
    if ((ctxt == NULL) || (ctxt->input == NULL))
 
9631
        return(-1);
 
9632
 
 
9633
    xmlDefaultSAXHandlerInit();
 
9634
 
 
9635
    xmlDetectSAX2(ctxt);
 
9636
 
 
9637
    GROW;
 
9638
 
 
9639
    /*
 
9640
     * SAX: beginning of the document processing.
 
9641
     */
 
9642
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
9643
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
9644
 
 
9645
    /* 
 
9646
     * Get the 4 first bytes and decode the charset
 
9647
     * if enc != XML_CHAR_ENCODING_NONE
 
9648
     * plug some encoding conversion routines.
 
9649
     */
 
9650
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
9651
        start[0] = RAW;
 
9652
        start[1] = NXT(1);
 
9653
        start[2] = NXT(2);
 
9654
        start[3] = NXT(3);
 
9655
        enc = xmlDetectCharEncoding(start, 4);
 
9656
        if (enc != XML_CHAR_ENCODING_NONE) {
 
9657
            xmlSwitchEncoding(ctxt, enc);
 
9658
        }
 
9659
    }
 
9660
 
 
9661
 
 
9662
    if (CUR == 0) {
 
9663
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
9664
    }
 
9665
 
 
9666
    /*
 
9667
     * Check for the XMLDecl in the Prolog.
 
9668
     */
 
9669
    GROW;
 
9670
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
9671
 
 
9672
        /*
 
9673
         * Note that we will switch encoding on the fly.
 
9674
         */
 
9675
        xmlParseXMLDecl(ctxt);
 
9676
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
9677
            /*
 
9678
             * The XML REC instructs us to stop parsing right here
 
9679
             */
 
9680
            return(-1);
 
9681
        }
 
9682
        SKIP_BLANKS;
 
9683
    } else {
 
9684
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
9685
    }
 
9686
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 
9687
        ctxt->sax->startDocument(ctxt->userData);
 
9688
 
 
9689
    /*
 
9690
     * Doing validity checking on chunk doesn't make sense
 
9691
     */
 
9692
    ctxt->instate = XML_PARSER_CONTENT;
 
9693
    ctxt->validate = 0;
 
9694
    ctxt->loadsubset = 0;
 
9695
    ctxt->depth = 0;
 
9696
 
 
9697
    xmlParseContent(ctxt);
 
9698
   
 
9699
    if ((RAW == '<') && (NXT(1) == '/')) {
 
9700
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
9701
    } else if (RAW != 0) {
 
9702
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
9703
    }
 
9704
 
 
9705
    /*
 
9706
     * SAX: end of the document processing.
 
9707
     */
 
9708
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
9709
        ctxt->sax->endDocument(ctxt->userData);
 
9710
 
 
9711
    if (! ctxt->wellFormed) return(-1);
 
9712
    return(0);
 
9713
}
 
9714
 
 
9715
#ifdef LIBXML_PUSH_ENABLED
 
9716
/************************************************************************
 
9717
 *                                                                      *
 
9718
 *              Progressive parsing interfaces                          *
 
9719
 *                                                                      *
 
9720
 ************************************************************************/
 
9721
 
 
9722
/**
 
9723
 * xmlParseLookupSequence:
 
9724
 * @ctxt:  an XML parser context
 
9725
 * @first:  the first char to lookup
 
9726
 * @next:  the next char to lookup or zero
 
9727
 * @third:  the next char to lookup or zero
 
9728
 *
 
9729
 * Try to find if a sequence (first, next, third) or  just (first next) or
 
9730
 * (first) is available in the input stream.
 
9731
 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
 
9732
 * to avoid rescanning sequences of bytes, it DOES change the state of the
 
9733
 * parser, do not use liberally.
 
9734
 *
 
9735
 * Returns the index to the current parsing point if the full sequence
 
9736
 *      is available, -1 otherwise.
 
9737
 */
 
9738
static int
 
9739
xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
 
9740
                       xmlChar next, xmlChar third) {
 
9741
    int base, len;
 
9742
    xmlParserInputPtr in;
 
9743
    const xmlChar *buf;
 
9744
 
 
9745
    in = ctxt->input;
 
9746
    if (in == NULL) return(-1);
 
9747
    base = in->cur - in->base;
 
9748
    if (base < 0) return(-1);
 
9749
    if (ctxt->checkIndex > base)
 
9750
        base = ctxt->checkIndex;
 
9751
    if (in->buf == NULL) {
 
9752
        buf = in->base;
 
9753
        len = in->length;
 
9754
    } else {
 
9755
        buf = in->buf->buffer->content;
 
9756
        len = in->buf->buffer->use;
 
9757
    }
 
9758
    /* take into account the sequence length */
 
9759
    if (third) len -= 2;
 
9760
    else if (next) len --;
 
9761
    for (;base < len;base++) {
 
9762
        if (buf[base] == first) {
 
9763
            if (third != 0) {
 
9764
                if ((buf[base + 1] != next) ||
 
9765
                    (buf[base + 2] != third)) continue;
 
9766
            } else if (next != 0) {
 
9767
                if (buf[base + 1] != next) continue;
 
9768
            }
 
9769
            ctxt->checkIndex = 0;
 
9770
#ifdef DEBUG_PUSH
 
9771
            if (next == 0)
 
9772
                xmlGenericError(xmlGenericErrorContext,
 
9773
                        "PP: lookup '%c' found at %d\n",
 
9774
                        first, base);
 
9775
            else if (third == 0)
 
9776
                xmlGenericError(xmlGenericErrorContext,
 
9777
                        "PP: lookup '%c%c' found at %d\n",
 
9778
                        first, next, base);
 
9779
            else 
 
9780
                xmlGenericError(xmlGenericErrorContext,
 
9781
                        "PP: lookup '%c%c%c' found at %d\n",
 
9782
                        first, next, third, base);
 
9783
#endif
 
9784
            return(base - (in->cur - in->base));
 
9785
        }
 
9786
    }
 
9787
    ctxt->checkIndex = base;
 
9788
#ifdef DEBUG_PUSH
 
9789
    if (next == 0)
 
9790
        xmlGenericError(xmlGenericErrorContext,
 
9791
                "PP: lookup '%c' failed\n", first);
 
9792
    else if (third == 0)
 
9793
        xmlGenericError(xmlGenericErrorContext,
 
9794
                "PP: lookup '%c%c' failed\n", first, next);
 
9795
    else        
 
9796
        xmlGenericError(xmlGenericErrorContext,
 
9797
                "PP: lookup '%c%c%c' failed\n", first, next, third);
 
9798
#endif
 
9799
    return(-1);
 
9800
}
 
9801
 
 
9802
/**
 
9803
 * xmlParseGetLasts:
 
9804
 * @ctxt:  an XML parser context
 
9805
 * @lastlt:  pointer to store the last '<' from the input
 
9806
 * @lastgt:  pointer to store the last '>' from the input
 
9807
 *
 
9808
 * Lookup the last < and > in the current chunk
 
9809
 */
 
9810
static void
 
9811
xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
 
9812
                 const xmlChar **lastgt) {
 
9813
    const xmlChar *tmp;
 
9814
 
 
9815
    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
 
9816
        xmlGenericError(xmlGenericErrorContext,
 
9817
                    "Internal error: xmlParseGetLasts\n");
 
9818
        return;
 
9819
    }
 
9820
    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
 
9821
        tmp = ctxt->input->end;
 
9822
        tmp--;
 
9823
        while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
 
9824
        if (tmp < ctxt->input->base) {
 
9825
            *lastlt = NULL;
 
9826
            *lastgt = NULL;
 
9827
        } else {
 
9828
            *lastlt = tmp;
 
9829
            tmp++;
 
9830
            while ((tmp < ctxt->input->end) && (*tmp != '>')) {
 
9831
                if (*tmp == '\'') {
 
9832
                    tmp++;
 
9833
                    while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
 
9834
                    if (tmp < ctxt->input->end) tmp++;
 
9835
                } else if (*tmp == '"') {
 
9836
                    tmp++;
 
9837
                    while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
 
9838
                    if (tmp < ctxt->input->end) tmp++;
 
9839
                } else
 
9840
                    tmp++;
 
9841
            }
 
9842
            if (tmp < ctxt->input->end)
 
9843
                *lastgt = tmp;
 
9844
            else {
 
9845
                tmp = *lastlt;
 
9846
                tmp--;
 
9847
                while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
 
9848
                if (tmp >= ctxt->input->base)
 
9849
                    *lastgt = tmp;
 
9850
                else
 
9851
                    *lastgt = NULL;
 
9852
            }
 
9853
        }
 
9854
    } else {
 
9855
        *lastlt = NULL;
 
9856
        *lastgt = NULL;
 
9857
    }
 
9858
}
 
9859
/**
 
9860
 * xmlCheckCdataPush:
 
9861
 * @cur: pointer to the bock of characters
 
9862
 * @len: length of the block in bytes
 
9863
 *
 
9864
 * Check that the block of characters is okay as SCdata content [20]
 
9865
 *
 
9866
 * Returns the number of bytes to pass if okay, a negative index where an
 
9867
 *         UTF-8 error occured otherwise
 
9868
 */
 
9869
static int
 
9870
xmlCheckCdataPush(const xmlChar *utf, int len) {
 
9871
    int ix;
 
9872
    unsigned char c;
 
9873
    int codepoint;
 
9874
 
 
9875
    if ((utf == NULL) || (len <= 0))
 
9876
        return(0);
 
9877
    
 
9878
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
 
9879
        c = utf[ix];
 
9880
        if ((c & 0x80) == 0x00) {       /* 1-byte code, starts with 10 */
 
9881
            if (c >= 0x20)
 
9882
                ix++;
 
9883
            else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
 
9884
                ix++;
 
9885
            else
 
9886
                return(-ix);
 
9887
        } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
 
9888
            if (ix + 2 > len) return(ix);
 
9889
            if ((utf[ix+1] & 0xc0 ) != 0x80)
 
9890
                return(-ix);
 
9891
            codepoint = (utf[ix] & 0x1f) << 6;
 
9892
            codepoint |= utf[ix+1] & 0x3f;
 
9893
            if (!xmlIsCharQ(codepoint))
 
9894
                return(-ix);
 
9895
            ix += 2;
 
9896
        } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
 
9897
            if (ix + 3 > len) return(ix);
 
9898
            if (((utf[ix+1] & 0xc0) != 0x80) ||
 
9899
                ((utf[ix+2] & 0xc0) != 0x80))
 
9900
                    return(-ix);
 
9901
            codepoint = (utf[ix] & 0xf) << 12;
 
9902
            codepoint |= (utf[ix+1] & 0x3f) << 6;
 
9903
            codepoint |= utf[ix+2] & 0x3f;
 
9904
            if (!xmlIsCharQ(codepoint))
 
9905
                return(-ix);
 
9906
            ix += 3;
 
9907
        } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
 
9908
            if (ix + 4 > len) return(ix);
 
9909
            if (((utf[ix+1] & 0xc0) != 0x80) ||
 
9910
                ((utf[ix+2] & 0xc0) != 0x80) ||
 
9911
                ((utf[ix+3] & 0xc0) != 0x80))
 
9912
                    return(-ix);
 
9913
            codepoint = (utf[ix] & 0x7) << 18;
 
9914
            codepoint |= (utf[ix+1] & 0x3f) << 12;
 
9915
            codepoint |= (utf[ix+2] & 0x3f) << 6;
 
9916
            codepoint |= utf[ix+3] & 0x3f;
 
9917
            if (!xmlIsCharQ(codepoint))
 
9918
                return(-ix);
 
9919
            ix += 4;
 
9920
        } else                          /* unknown encoding */
 
9921
            return(-ix);
 
9922
      }
 
9923
      return(ix);
 
9924
}
 
9925
 
 
9926
/**
 
9927
 * xmlParseTryOrFinish:
 
9928
 * @ctxt:  an XML parser context
 
9929
 * @terminate:  last chunk indicator
 
9930
 *
 
9931
 * Try to progress on parsing
 
9932
 *
 
9933
 * Returns zero if no parsing was possible
 
9934
 */
 
9935
static int
 
9936
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 
9937
    int ret = 0;
 
9938
    int avail, tlen;
 
9939
    xmlChar cur, next;
 
9940
    const xmlChar *lastlt, *lastgt;
 
9941
 
 
9942
    if (ctxt->input == NULL)
 
9943
        return(0);
 
9944
 
 
9945
#ifdef DEBUG_PUSH
 
9946
    switch (ctxt->instate) {
 
9947
        case XML_PARSER_EOF:
 
9948
            xmlGenericError(xmlGenericErrorContext,
 
9949
                    "PP: try EOF\n"); break;
 
9950
        case XML_PARSER_START:
 
9951
            xmlGenericError(xmlGenericErrorContext,
 
9952
                    "PP: try START\n"); break;
 
9953
        case XML_PARSER_MISC:
 
9954
            xmlGenericError(xmlGenericErrorContext,
 
9955
                    "PP: try MISC\n");break;
 
9956
        case XML_PARSER_COMMENT:
 
9957
            xmlGenericError(xmlGenericErrorContext,
 
9958
                    "PP: try COMMENT\n");break;
 
9959
        case XML_PARSER_PROLOG:
 
9960
            xmlGenericError(xmlGenericErrorContext,
 
9961
                    "PP: try PROLOG\n");break;
 
9962
        case XML_PARSER_START_TAG:
 
9963
            xmlGenericError(xmlGenericErrorContext,
 
9964
                    "PP: try START_TAG\n");break;
 
9965
        case XML_PARSER_CONTENT:
 
9966
            xmlGenericError(xmlGenericErrorContext,
 
9967
                    "PP: try CONTENT\n");break;
 
9968
        case XML_PARSER_CDATA_SECTION:
 
9969
            xmlGenericError(xmlGenericErrorContext,
 
9970
                    "PP: try CDATA_SECTION\n");break;
 
9971
        case XML_PARSER_END_TAG:
 
9972
            xmlGenericError(xmlGenericErrorContext,
 
9973
                    "PP: try END_TAG\n");break;
 
9974
        case XML_PARSER_ENTITY_DECL:
 
9975
            xmlGenericError(xmlGenericErrorContext,
 
9976
                    "PP: try ENTITY_DECL\n");break;
 
9977
        case XML_PARSER_ENTITY_VALUE:
 
9978
            xmlGenericError(xmlGenericErrorContext,
 
9979
                    "PP: try ENTITY_VALUE\n");break;
 
9980
        case XML_PARSER_ATTRIBUTE_VALUE:
 
9981
            xmlGenericError(xmlGenericErrorContext,
 
9982
                    "PP: try ATTRIBUTE_VALUE\n");break;
 
9983
        case XML_PARSER_DTD:
 
9984
            xmlGenericError(xmlGenericErrorContext,
 
9985
                    "PP: try DTD\n");break;
 
9986
        case XML_PARSER_EPILOG:
 
9987
            xmlGenericError(xmlGenericErrorContext,
 
9988
                    "PP: try EPILOG\n");break;
 
9989
        case XML_PARSER_PI:
 
9990
            xmlGenericError(xmlGenericErrorContext,
 
9991
                    "PP: try PI\n");break;
 
9992
        case XML_PARSER_IGNORE:
 
9993
            xmlGenericError(xmlGenericErrorContext,
 
9994
                    "PP: try IGNORE\n");break;
 
9995
    }
 
9996
#endif
 
9997
 
 
9998
    if ((ctxt->input != NULL) &&
 
9999
        (ctxt->input->cur - ctxt->input->base > 4096)) {
 
10000
        xmlSHRINK(ctxt);
 
10001
        ctxt->checkIndex = 0;
 
10002
    }
 
10003
    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
10004
 
 
10005
    while (1) {
 
10006
        if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
10007
            return(0);
 
10008
 
 
10009
        
 
10010
        /*
 
10011
         * Pop-up of finished entities.
 
10012
         */
 
10013
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
10014
            xmlPopInput(ctxt);
 
10015
 
 
10016
        if (ctxt->input == NULL) break;
 
10017
        if (ctxt->input->buf == NULL)
 
10018
            avail = ctxt->input->length -
 
10019
                    (ctxt->input->cur - ctxt->input->base);
 
10020
        else {
 
10021
            /*
 
10022
             * If we are operating on converted input, try to flush
 
10023
             * remainng chars to avoid them stalling in the non-converted
 
10024
             * buffer.
 
10025
             */
 
10026
            if ((ctxt->input->buf->raw != NULL) &&
 
10027
                (ctxt->input->buf->raw->use > 0)) {
 
10028
                int base = ctxt->input->base -
 
10029
                           ctxt->input->buf->buffer->content;
 
10030
                int current = ctxt->input->cur - ctxt->input->base;
 
10031
 
 
10032
                xmlParserInputBufferPush(ctxt->input->buf, 0, "");
 
10033
                ctxt->input->base = ctxt->input->buf->buffer->content + base;
 
10034
                ctxt->input->cur = ctxt->input->base + current;
 
10035
                ctxt->input->end =
 
10036
                    &ctxt->input->buf->buffer->content[
 
10037
                                       ctxt->input->buf->buffer->use];
 
10038
            }
 
10039
            avail = ctxt->input->buf->buffer->use -
 
10040
                    (ctxt->input->cur - ctxt->input->base);
 
10041
        }
 
10042
        if (avail < 1)
 
10043
            goto done;
 
10044
        switch (ctxt->instate) {
 
10045
            case XML_PARSER_EOF:
 
10046
                /*
 
10047
                 * Document parsing is done !
 
10048
                 */
 
10049
                goto done;
 
10050
            case XML_PARSER_START:
 
10051
                if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
 
10052
                    xmlChar start[4];
 
10053
                    xmlCharEncoding enc;
 
10054
 
 
10055
                    /*
 
10056
                     * Very first chars read from the document flow.
 
10057
                     */
 
10058
                    if (avail < 4)
 
10059
                        goto done;
 
10060
 
 
10061
                    /* 
 
10062
                     * Get the 4 first bytes and decode the charset
 
10063
                     * if enc != XML_CHAR_ENCODING_NONE
 
10064
                     * plug some encoding conversion routines,
 
10065
                     * else xmlSwitchEncoding will set to (default)
 
10066
                     * UTF8.
 
10067
                     */
 
10068
                    start[0] = RAW;
 
10069
                    start[1] = NXT(1);
 
10070
                    start[2] = NXT(2);
 
10071
                    start[3] = NXT(3);
 
10072
                    enc = xmlDetectCharEncoding(start, 4);
 
10073
                    xmlSwitchEncoding(ctxt, enc);
 
10074
                    break;
 
10075
                }
 
10076
 
 
10077
                if (avail < 2)
 
10078
                    goto done;
 
10079
                cur = ctxt->input->cur[0];
 
10080
                next = ctxt->input->cur[1];
 
10081
                if (cur == 0) {
 
10082
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10083
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
10084
                                                      &xmlDefaultSAXLocator);
 
10085
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
10086
                    ctxt->instate = XML_PARSER_EOF;
 
10087
#ifdef DEBUG_PUSH
 
10088
                    xmlGenericError(xmlGenericErrorContext,
 
10089
                            "PP: entering EOF\n");
 
10090
#endif
 
10091
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10092
                        ctxt->sax->endDocument(ctxt->userData);
 
10093
                    goto done;
 
10094
                }
 
10095
                if ((cur == '<') && (next == '?')) {
 
10096
                    /* PI or XML decl */
 
10097
                    if (avail < 5) return(ret);
 
10098
                    if ((!terminate) &&
 
10099
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
10100
                        return(ret);
 
10101
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10102
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
10103
                                                      &xmlDefaultSAXLocator);
 
10104
                    if ((ctxt->input->cur[2] == 'x') &&
 
10105
                        (ctxt->input->cur[3] == 'm') &&
 
10106
                        (ctxt->input->cur[4] == 'l') &&
 
10107
                        (IS_BLANK_CH(ctxt->input->cur[5]))) {
 
10108
                        ret += 5;
 
10109
#ifdef DEBUG_PUSH
 
10110
                        xmlGenericError(xmlGenericErrorContext,
 
10111
                                "PP: Parsing XML Decl\n");
 
10112
#endif
 
10113
                        xmlParseXMLDecl(ctxt);
 
10114
                        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10115
                            /*
 
10116
                             * The XML REC instructs us to stop parsing right
 
10117
                             * here
 
10118
                             */
 
10119
                            ctxt->instate = XML_PARSER_EOF;
 
10120
                            return(0);
 
10121
                        }
 
10122
                        ctxt->standalone = ctxt->input->standalone;
 
10123
                        if ((ctxt->encoding == NULL) &&
 
10124
                            (ctxt->input->encoding != NULL))
 
10125
                            ctxt->encoding = xmlStrdup(ctxt->input->encoding);
 
10126
                        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
10127
                            (!ctxt->disableSAX))
 
10128
                            ctxt->sax->startDocument(ctxt->userData);
 
10129
                        ctxt->instate = XML_PARSER_MISC;
 
10130
#ifdef DEBUG_PUSH
 
10131
                        xmlGenericError(xmlGenericErrorContext,
 
10132
                                "PP: entering MISC\n");
 
10133
#endif
 
10134
                    } else {
 
10135
                        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
10136
                        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
10137
                            (!ctxt->disableSAX))
 
10138
                            ctxt->sax->startDocument(ctxt->userData);
 
10139
                        ctxt->instate = XML_PARSER_MISC;
 
10140
#ifdef DEBUG_PUSH
 
10141
                        xmlGenericError(xmlGenericErrorContext,
 
10142
                                "PP: entering MISC\n");
 
10143
#endif
 
10144
                    }
 
10145
                } else {
 
10146
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10147
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
10148
                                                      &xmlDefaultSAXLocator);
 
10149
                    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
10150
                    if (ctxt->version == NULL) {
 
10151
                        xmlErrMemory(ctxt, NULL);
 
10152
                        break;
 
10153
                    }
 
10154
                    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
10155
                        (!ctxt->disableSAX))
 
10156
                        ctxt->sax->startDocument(ctxt->userData);
 
10157
                    ctxt->instate = XML_PARSER_MISC;
 
10158
#ifdef DEBUG_PUSH
 
10159
                    xmlGenericError(xmlGenericErrorContext,
 
10160
                            "PP: entering MISC\n");
 
10161
#endif
 
10162
                }
 
10163
                break;
 
10164
            case XML_PARSER_START_TAG: {
 
10165
                const xmlChar *name;
 
10166
                const xmlChar *prefix;
 
10167
                const xmlChar *URI;
 
10168
                int nsNr = ctxt->nsNr;
 
10169
 
 
10170
                if ((avail < 2) && (ctxt->inputNr == 1))
 
10171
                    goto done;
 
10172
                cur = ctxt->input->cur[0];
 
10173
                if (cur != '<') {
 
10174
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
10175
                    ctxt->instate = XML_PARSER_EOF;
 
10176
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10177
                        ctxt->sax->endDocument(ctxt->userData);
 
10178
                    goto done;
 
10179
                }
 
10180
                if (!terminate) {
 
10181
                    if (ctxt->progressive) {
 
10182
                        /* > can be found unescaped in attribute values */
 
10183
                        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
 
10184
                            goto done;
 
10185
                    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
 
10186
                        goto done;
 
10187
                    }
 
10188
                }
 
10189
                if (ctxt->spaceNr == 0)
 
10190
                    spacePush(ctxt, -1);
 
10191
                else if (*ctxt->space == -2)
 
10192
                    spacePush(ctxt, -1);
 
10193
                else
 
10194
                    spacePush(ctxt, *ctxt->space);
 
10195
#ifdef LIBXML_SAX1_ENABLED
 
10196
                if (ctxt->sax2)
 
10197
#endif /* LIBXML_SAX1_ENABLED */
 
10198
                    name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
 
10199
#ifdef LIBXML_SAX1_ENABLED
 
10200
                else
 
10201
                    name = xmlParseStartTag(ctxt);
 
10202
#endif /* LIBXML_SAX1_ENABLED */
 
10203
                if (name == NULL) {
 
10204
                    spacePop(ctxt);
 
10205
                    ctxt->instate = XML_PARSER_EOF;
 
10206
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10207
                        ctxt->sax->endDocument(ctxt->userData);
 
10208
                    goto done;
 
10209
                }
 
10210
#ifdef LIBXML_VALID_ENABLED
 
10211
                /*
 
10212
                 * [ VC: Root Element Type ]
 
10213
                 * The Name in the document type declaration must match
 
10214
                 * the element type of the root element. 
 
10215
                 */
 
10216
                if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
 
10217
                    ctxt->node && (ctxt->node == ctxt->myDoc->children))
 
10218
                    ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
 
10219
#endif /* LIBXML_VALID_ENABLED */
 
10220
 
 
10221
                /*
 
10222
                 * Check for an Empty Element.
 
10223
                 */
 
10224
                if ((RAW == '/') && (NXT(1) == '>')) {
 
10225
                    SKIP(2);
 
10226
 
 
10227
                    if (ctxt->sax2) {
 
10228
                        if ((ctxt->sax != NULL) &&
 
10229
                            (ctxt->sax->endElementNs != NULL) &&
 
10230
                            (!ctxt->disableSAX))
 
10231
                            ctxt->sax->endElementNs(ctxt->userData, name,
 
10232
                                                    prefix, URI);
 
10233
                        if (ctxt->nsNr - nsNr > 0)
 
10234
                            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10235
#ifdef LIBXML_SAX1_ENABLED
 
10236
                    } else {
 
10237
                        if ((ctxt->sax != NULL) &&
 
10238
                            (ctxt->sax->endElement != NULL) &&
 
10239
                            (!ctxt->disableSAX))
 
10240
                            ctxt->sax->endElement(ctxt->userData, name);
 
10241
#endif /* LIBXML_SAX1_ENABLED */
 
10242
                    }
 
10243
                    spacePop(ctxt);
 
10244
                    if (ctxt->nameNr == 0) {
 
10245
                        ctxt->instate = XML_PARSER_EPILOG;
 
10246
                    } else {
 
10247
                        ctxt->instate = XML_PARSER_CONTENT;
 
10248
                    }
 
10249
                    break;
 
10250
                }
 
10251
                if (RAW == '>') {
 
10252
                    NEXT;
 
10253
                } else {
 
10254
                    xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
 
10255
                                         "Couldn't find end of Start Tag %s\n",
 
10256
                                         name);
 
10257
                    nodePop(ctxt);
 
10258
                    spacePop(ctxt);
 
10259
                }
 
10260
                if (ctxt->sax2)
 
10261
                    nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
 
10262
#ifdef LIBXML_SAX1_ENABLED
 
10263
                else
 
10264
                    namePush(ctxt, name);
 
10265
#endif /* LIBXML_SAX1_ENABLED */
 
10266
 
 
10267
                ctxt->instate = XML_PARSER_CONTENT;
 
10268
                break;
 
10269
            }
 
10270
            case XML_PARSER_CONTENT: {
 
10271
                const xmlChar *test;
 
10272
                unsigned int cons;
 
10273
                if ((avail < 2) && (ctxt->inputNr == 1))
 
10274
                    goto done;
 
10275
                cur = ctxt->input->cur[0];
 
10276
                next = ctxt->input->cur[1];
 
10277
 
 
10278
                test = CUR_PTR;
 
10279
                cons = ctxt->input->consumed;
 
10280
                if ((cur == '<') && (next == '/')) {
 
10281
                    ctxt->instate = XML_PARSER_END_TAG;
 
10282
                    break;
 
10283
                } else if ((cur == '<') && (next == '?')) {
 
10284
                    if ((!terminate) &&
 
10285
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
10286
                        goto done;
 
10287
                    xmlParsePI(ctxt);
 
10288
                } else if ((cur == '<') && (next != '!')) {
 
10289
                    ctxt->instate = XML_PARSER_START_TAG;
 
10290
                    break;
 
10291
                } else if ((cur == '<') && (next == '!') &&
 
10292
                           (ctxt->input->cur[2] == '-') &&
 
10293
                           (ctxt->input->cur[3] == '-')) {
 
10294
                    int term;
 
10295
 
 
10296
                    if (avail < 4)
 
10297
                        goto done;
 
10298
                    ctxt->input->cur += 4;
 
10299
                    term = xmlParseLookupSequence(ctxt, '-', '-', '>');
 
10300
                    ctxt->input->cur -= 4;
 
10301
                    if ((!terminate) && (term < 0))
 
10302
                        goto done;
 
10303
                    xmlParseComment(ctxt);
 
10304
                    ctxt->instate = XML_PARSER_CONTENT;
 
10305
                } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
 
10306
                    (ctxt->input->cur[2] == '[') &&
 
10307
                    (ctxt->input->cur[3] == 'C') &&
 
10308
                    (ctxt->input->cur[4] == 'D') &&
 
10309
                    (ctxt->input->cur[5] == 'A') &&
 
10310
                    (ctxt->input->cur[6] == 'T') &&
 
10311
                    (ctxt->input->cur[7] == 'A') &&
 
10312
                    (ctxt->input->cur[8] == '[')) {
 
10313
                    SKIP(9);
 
10314
                    ctxt->instate = XML_PARSER_CDATA_SECTION;
 
10315
                    break;
 
10316
                } else if ((cur == '<') && (next == '!') &&
 
10317
                           (avail < 9)) {
 
10318
                    goto done;
 
10319
                } else if (cur == '&') {
 
10320
                    if ((!terminate) &&
 
10321
                        (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
 
10322
                        goto done;
 
10323
                    xmlParseReference(ctxt);
 
10324
                } else {
 
10325
                    /* TODO Avoid the extra copy, handle directly !!! */
 
10326
                    /*
 
10327
                     * Goal of the following test is:
 
10328
                     *  - minimize calls to the SAX 'character' callback
 
10329
                     *    when they are mergeable
 
10330
                     *  - handle an problem for isBlank when we only parse
 
10331
                     *    a sequence of blank chars and the next one is
 
10332
                     *    not available to check against '<' presence.
 
10333
                     *  - tries to homogenize the differences in SAX
 
10334
                     *    callbacks between the push and pull versions
 
10335
                     *    of the parser.
 
10336
                     */
 
10337
                    if ((ctxt->inputNr == 1) &&
 
10338
                        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
 
10339
                        if (!terminate) {
 
10340
                            if (ctxt->progressive) {
 
10341
                                if ((lastlt == NULL) ||
 
10342
                                    (ctxt->input->cur > lastlt))
 
10343
                                    goto done;
 
10344
                            } else if (xmlParseLookupSequence(ctxt,
 
10345
                                                              '<', 0, 0) < 0) {
 
10346
                                goto done;
 
10347
                            }
 
10348
                        }
 
10349
                    }
 
10350
                    ctxt->checkIndex = 0;
 
10351
                    xmlParseCharData(ctxt, 0);
 
10352
                }
 
10353
                /*
 
10354
                 * Pop-up of finished entities.
 
10355
                 */
 
10356
                while ((RAW == 0) && (ctxt->inputNr > 1))
 
10357
                    xmlPopInput(ctxt);
 
10358
                if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
 
10359
                    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
10360
                                "detected an error in element content\n");
 
10361
                    ctxt->instate = XML_PARSER_EOF;
 
10362
                    break;
 
10363
                }
 
10364
                break;
 
10365
            }
 
10366
            case XML_PARSER_END_TAG:
 
10367
                if (avail < 2)
 
10368
                    goto done;
 
10369
                if (!terminate) {
 
10370
                    if (ctxt->progressive) {
 
10371
                        /* > can be found unescaped in attribute values */
 
10372
                        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
 
10373
                            goto done;
 
10374
                    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
 
10375
                        goto done;
 
10376
                    }
 
10377
                }
 
10378
                if (ctxt->sax2) {
 
10379
                    xmlParseEndTag2(ctxt,
 
10380
                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
 
10381
                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
 
10382
                       (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
 
10383
                    nameNsPop(ctxt);
 
10384
                }
 
10385
#ifdef LIBXML_SAX1_ENABLED
 
10386
                  else
 
10387
                    xmlParseEndTag1(ctxt, 0);
 
10388
#endif /* LIBXML_SAX1_ENABLED */
 
10389
                if (ctxt->nameNr == 0) {
 
10390
                    ctxt->instate = XML_PARSER_EPILOG;
 
10391
                } else {
 
10392
                    ctxt->instate = XML_PARSER_CONTENT;
 
10393
                }
 
10394
                break;
 
10395
            case XML_PARSER_CDATA_SECTION: {
 
10396
                /*
 
10397
                 * The Push mode need to have the SAX callback for 
 
10398
                 * cdataBlock merge back contiguous callbacks.
 
10399
                 */
 
10400
                int base;
 
10401
 
 
10402
                base = xmlParseLookupSequence(ctxt, ']', ']', '>');
 
10403
                if (base < 0) {
 
10404
                    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
 
10405
                        int tmp;
 
10406
 
 
10407
                        tmp = xmlCheckCdataPush(ctxt->input->cur, 
 
10408
                                                XML_PARSER_BIG_BUFFER_SIZE);
 
10409
                        if (tmp < 0) {
 
10410
                            tmp = -tmp;
 
10411
                            ctxt->input->cur += tmp;
 
10412
                            goto encoding_error;
 
10413
                        }
 
10414
                        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
10415
                            if (ctxt->sax->cdataBlock != NULL)
 
10416
                                ctxt->sax->cdataBlock(ctxt->userData,
 
10417
                                                      ctxt->input->cur, tmp);
 
10418
                            else if (ctxt->sax->characters != NULL)
 
10419
                                ctxt->sax->characters(ctxt->userData,
 
10420
                                                      ctxt->input->cur, tmp);
 
10421
                        }
 
10422
                        SKIPL(tmp);
 
10423
                        ctxt->checkIndex = 0;
 
10424
                    }
 
10425
                    goto done;
 
10426
                } else {
 
10427
                    int tmp;
 
10428
 
 
10429
                    tmp = xmlCheckCdataPush(ctxt->input->cur, base);
 
10430
                    if ((tmp < 0) || (tmp != base)) {
 
10431
                        tmp = -tmp;
 
10432
                        ctxt->input->cur += tmp;
 
10433
                        goto encoding_error;
 
10434
                    }
 
10435
                    if ((ctxt->sax != NULL) && (base == 0) &&
 
10436
                        (ctxt->sax->cdataBlock != NULL) &&
 
10437
                        (!ctxt->disableSAX)) {
 
10438
                        /*
 
10439
                         * Special case to provide identical behaviour
 
10440
                         * between pull and push parsers on enpty CDATA
 
10441
                         * sections
 
10442
                         */
 
10443
                         if ((ctxt->input->cur - ctxt->input->base >= 9) &&
 
10444
                             (!strncmp((const char *)&ctxt->input->cur[-9],
 
10445
                                       "<![CDATA[", 9)))
 
10446
                             ctxt->sax->cdataBlock(ctxt->userData,
 
10447
                                                   BAD_CAST "", 0);
 
10448
                    } else if ((ctxt->sax != NULL) && (base > 0) &&
 
10449
                        (!ctxt->disableSAX)) {
 
10450
                        if (ctxt->sax->cdataBlock != NULL)
 
10451
                            ctxt->sax->cdataBlock(ctxt->userData,
 
10452
                                                  ctxt->input->cur, base);
 
10453
                        else if (ctxt->sax->characters != NULL)
 
10454
                            ctxt->sax->characters(ctxt->userData,
 
10455
                                                  ctxt->input->cur, base);
 
10456
                    }
 
10457
                    SKIPL(base + 3);
 
10458
                    ctxt->checkIndex = 0;
 
10459
                    ctxt->instate = XML_PARSER_CONTENT;
 
10460
#ifdef DEBUG_PUSH
 
10461
                    xmlGenericError(xmlGenericErrorContext,
 
10462
                            "PP: entering CONTENT\n");
 
10463
#endif
 
10464
                }
 
10465
                break;
 
10466
            }
 
10467
            case XML_PARSER_MISC:
 
10468
                SKIP_BLANKS;
 
10469
                if (ctxt->input->buf == NULL)
 
10470
                    avail = ctxt->input->length -
 
10471
                            (ctxt->input->cur - ctxt->input->base);
 
10472
                else
 
10473
                    avail = ctxt->input->buf->buffer->use -
 
10474
                            (ctxt->input->cur - ctxt->input->base);
 
10475
                if (avail < 2)
 
10476
                    goto done;
 
10477
                cur = ctxt->input->cur[0];
 
10478
                next = ctxt->input->cur[1];
 
10479
                if ((cur == '<') && (next == '?')) {
 
10480
                    if ((!terminate) &&
 
10481
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
10482
                        goto done;
 
10483
#ifdef DEBUG_PUSH
 
10484
                    xmlGenericError(xmlGenericErrorContext,
 
10485
                            "PP: Parsing PI\n");
 
10486
#endif
 
10487
                    xmlParsePI(ctxt);
 
10488
                    ctxt->checkIndex = 0;
 
10489
                } else if ((cur == '<') && (next == '!') &&
 
10490
                    (ctxt->input->cur[2] == '-') &&
 
10491
                    (ctxt->input->cur[3] == '-')) {
 
10492
                    if ((!terminate) &&
 
10493
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
 
10494
                        goto done;
 
10495
#ifdef DEBUG_PUSH
 
10496
                    xmlGenericError(xmlGenericErrorContext,
 
10497
                            "PP: Parsing Comment\n");
 
10498
#endif
 
10499
                    xmlParseComment(ctxt);
 
10500
                    ctxt->instate = XML_PARSER_MISC;
 
10501
                    ctxt->checkIndex = 0;
 
10502
                } else if ((cur == '<') && (next == '!') &&
 
10503
                    (ctxt->input->cur[2] == 'D') &&
 
10504
                    (ctxt->input->cur[3] == 'O') &&
 
10505
                    (ctxt->input->cur[4] == 'C') &&
 
10506
                    (ctxt->input->cur[5] == 'T') &&
 
10507
                    (ctxt->input->cur[6] == 'Y') &&
 
10508
                    (ctxt->input->cur[7] == 'P') &&
 
10509
                    (ctxt->input->cur[8] == 'E')) {
 
10510
                    if ((!terminate) &&
 
10511
                        (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
 
10512
                        goto done;
 
10513
#ifdef DEBUG_PUSH
 
10514
                    xmlGenericError(xmlGenericErrorContext,
 
10515
                            "PP: Parsing internal subset\n");
 
10516
#endif
 
10517
                    ctxt->inSubset = 1;
 
10518
                    xmlParseDocTypeDecl(ctxt);
 
10519
                    if (RAW == '[') {
 
10520
                        ctxt->instate = XML_PARSER_DTD;
 
10521
#ifdef DEBUG_PUSH
 
10522
                        xmlGenericError(xmlGenericErrorContext,
 
10523
                                "PP: entering DTD\n");
 
10524
#endif
 
10525
                    } else {
 
10526
                        /*
 
10527
                         * Create and update the external subset.
 
10528
                         */
 
10529
                        ctxt->inSubset = 2;
 
10530
                        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
10531
                            (ctxt->sax->externalSubset != NULL))
 
10532
                            ctxt->sax->externalSubset(ctxt->userData,
 
10533
                                    ctxt->intSubName, ctxt->extSubSystem,
 
10534
                                    ctxt->extSubURI);
 
10535
                        ctxt->inSubset = 0;
 
10536
                        xmlCleanSpecialAttr(ctxt);
 
10537
                        ctxt->instate = XML_PARSER_PROLOG;
 
10538
#ifdef DEBUG_PUSH
 
10539
                        xmlGenericError(xmlGenericErrorContext,
 
10540
                                "PP: entering PROLOG\n");
 
10541
#endif
 
10542
                    }
 
10543
                } else if ((cur == '<') && (next == '!') &&
 
10544
                           (avail < 9)) {
 
10545
                    goto done;
 
10546
                } else {
 
10547
                    ctxt->instate = XML_PARSER_START_TAG;
 
10548
                    ctxt->progressive = 1;
 
10549
                    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
10550
#ifdef DEBUG_PUSH
 
10551
                    xmlGenericError(xmlGenericErrorContext,
 
10552
                            "PP: entering START_TAG\n");
 
10553
#endif
 
10554
                }
 
10555
                break;
 
10556
            case XML_PARSER_PROLOG:
 
10557
                SKIP_BLANKS;
 
10558
                if (ctxt->input->buf == NULL)
 
10559
                    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
 
10560
                else
 
10561
                    avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
 
10562
                if (avail < 2) 
 
10563
                    goto done;
 
10564
                cur = ctxt->input->cur[0];
 
10565
                next = ctxt->input->cur[1];
 
10566
                if ((cur == '<') && (next == '?')) {
 
10567
                    if ((!terminate) &&
 
10568
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
10569
                        goto done;
 
10570
#ifdef DEBUG_PUSH
 
10571
                    xmlGenericError(xmlGenericErrorContext,
 
10572
                            "PP: Parsing PI\n");
 
10573
#endif
 
10574
                    xmlParsePI(ctxt);
 
10575
                } else if ((cur == '<') && (next == '!') &&
 
10576
                    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
 
10577
                    if ((!terminate) &&
 
10578
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
 
10579
                        goto done;
 
10580
#ifdef DEBUG_PUSH
 
10581
                    xmlGenericError(xmlGenericErrorContext,
 
10582
                            "PP: Parsing Comment\n");
 
10583
#endif
 
10584
                    xmlParseComment(ctxt);
 
10585
                    ctxt->instate = XML_PARSER_PROLOG;
 
10586
                } else if ((cur == '<') && (next == '!') &&
 
10587
                           (avail < 4)) {
 
10588
                    goto done;
 
10589
                } else {
 
10590
                    ctxt->instate = XML_PARSER_START_TAG;
 
10591
                    if (ctxt->progressive == 0)
 
10592
                        ctxt->progressive = 1;
 
10593
                    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
10594
#ifdef DEBUG_PUSH
 
10595
                    xmlGenericError(xmlGenericErrorContext,
 
10596
                            "PP: entering START_TAG\n");
 
10597
#endif
 
10598
                }
 
10599
                break;
 
10600
            case XML_PARSER_EPILOG:
 
10601
                SKIP_BLANKS;
 
10602
                if (ctxt->input->buf == NULL)
 
10603
                    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
 
10604
                else
 
10605
                    avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
 
10606
                if (avail < 2)
 
10607
                    goto done;
 
10608
                cur = ctxt->input->cur[0];
 
10609
                next = ctxt->input->cur[1];
 
10610
                if ((cur == '<') && (next == '?')) {
 
10611
                    if ((!terminate) &&
 
10612
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
10613
                        goto done;
 
10614
#ifdef DEBUG_PUSH
 
10615
                    xmlGenericError(xmlGenericErrorContext,
 
10616
                            "PP: Parsing PI\n");
 
10617
#endif
 
10618
                    xmlParsePI(ctxt);
 
10619
                    ctxt->instate = XML_PARSER_EPILOG;
 
10620
                } else if ((cur == '<') && (next == '!') &&
 
10621
                    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
 
10622
                    if ((!terminate) &&
 
10623
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
 
10624
                        goto done;
 
10625
#ifdef DEBUG_PUSH
 
10626
                    xmlGenericError(xmlGenericErrorContext,
 
10627
                            "PP: Parsing Comment\n");
 
10628
#endif
 
10629
                    xmlParseComment(ctxt);
 
10630
                    ctxt->instate = XML_PARSER_EPILOG;
 
10631
                } else if ((cur == '<') && (next == '!') &&
 
10632
                           (avail < 4)) {
 
10633
                    goto done;
 
10634
                } else {
 
10635
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
10636
                    ctxt->instate = XML_PARSER_EOF;
 
10637
#ifdef DEBUG_PUSH
 
10638
                    xmlGenericError(xmlGenericErrorContext,
 
10639
                            "PP: entering EOF\n");
 
10640
#endif
 
10641
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10642
                        ctxt->sax->endDocument(ctxt->userData);
 
10643
                    goto done;
 
10644
                }
 
10645
                break;
 
10646
            case XML_PARSER_DTD: {
 
10647
                /*
 
10648
                 * Sorry but progressive parsing of the internal subset
 
10649
                 * is not expected to be supported. We first check that
 
10650
                 * the full content of the internal subset is available and
 
10651
                 * the parsing is launched only at that point.
 
10652
                 * Internal subset ends up with "']' S? '>'" in an unescaped
 
10653
                 * section and not in a ']]>' sequence which are conditional
 
10654
                 * sections (whoever argued to keep that crap in XML deserve
 
10655
                 * a place in hell !).
 
10656
                 */
 
10657
                int base, i;
 
10658
                xmlChar *buf;
 
10659
                xmlChar quote = 0;
 
10660
 
 
10661
                base = ctxt->input->cur - ctxt->input->base;
 
10662
                if (base < 0) return(0);
 
10663
                if (ctxt->checkIndex > base)
 
10664
                    base = ctxt->checkIndex;
 
10665
                buf = ctxt->input->buf->buffer->content;
 
10666
                for (;(unsigned int) base < ctxt->input->buf->buffer->use;
 
10667
                     base++) {
 
10668
                    if (quote != 0) {
 
10669
                        if (buf[base] == quote)
 
10670
                            quote = 0;
 
10671
                        continue;    
 
10672
                    }
 
10673
                    if ((quote == 0) && (buf[base] == '<')) {
 
10674
                        int found  = 0;
 
10675
                        /* special handling of comments */
 
10676
                        if (((unsigned int) base + 4 <
 
10677
                             ctxt->input->buf->buffer->use) &&
 
10678
                            (buf[base + 1] == '!') &&
 
10679
                            (buf[base + 2] == '-') &&
 
10680
                            (buf[base + 3] == '-')) {
 
10681
                            for (;(unsigned int) base + 3 <
 
10682
                                  ctxt->input->buf->buffer->use; base++) {
 
10683
                                if ((buf[base] == '-') &&
 
10684
                                    (buf[base + 1] == '-') &&
 
10685
                                    (buf[base + 2] == '>')) {
 
10686
                                    found = 1;
 
10687
                                    base += 2;
 
10688
                                    break;
 
10689
                                }
 
10690
                            }
 
10691
                            if (!found) {
 
10692
#if 0
 
10693
                                fprintf(stderr, "unfinished comment\n");
 
10694
#endif
 
10695
                                break; /* for */
 
10696
                            }
 
10697
                            continue;
 
10698
                        }
 
10699
                    }
 
10700
                    if (buf[base] == '"') {
 
10701
                        quote = '"';
 
10702
                        continue;
 
10703
                    }
 
10704
                    if (buf[base] == '\'') {
 
10705
                        quote = '\'';
 
10706
                        continue;
 
10707
                    }
 
10708
                    if (buf[base] == ']') {
 
10709
#if 0
 
10710
                        fprintf(stderr, "%c%c%c%c: ", buf[base],
 
10711
                                buf[base + 1], buf[base + 2], buf[base + 3]);
 
10712
#endif
 
10713
                        if ((unsigned int) base +1 >=
 
10714
                            ctxt->input->buf->buffer->use)
 
10715
                            break;
 
10716
                        if (buf[base + 1] == ']') {
 
10717
                            /* conditional crap, skip both ']' ! */
 
10718
                            base++;
 
10719
                            continue;
 
10720
                        }
 
10721
                        for (i = 1;
 
10722
                     (unsigned int) base + i < ctxt->input->buf->buffer->use;
 
10723
                             i++) {
 
10724
                            if (buf[base + i] == '>') {
 
10725
#if 0
 
10726
                                fprintf(stderr, "found\n");
 
10727
#endif
 
10728
                                goto found_end_int_subset;
 
10729
                            }
 
10730
                            if (!IS_BLANK_CH(buf[base + i])) {
 
10731
#if 0
 
10732
                                fprintf(stderr, "not found\n");
 
10733
#endif
 
10734
                                goto not_end_of_int_subset;
 
10735
                            }
 
10736
                        }
 
10737
#if 0
 
10738
                        fprintf(stderr, "end of stream\n");
 
10739
#endif
 
10740
                        break;
 
10741
                        
 
10742
                    }
 
10743
not_end_of_int_subset:
 
10744
                    continue; /* for */
 
10745
                }
 
10746
                /*
 
10747
                 * We didn't found the end of the Internal subset
 
10748
                 */
 
10749
#ifdef DEBUG_PUSH
 
10750
                if (next == 0)
 
10751
                    xmlGenericError(xmlGenericErrorContext,
 
10752
                            "PP: lookup of int subset end filed\n");
 
10753
#endif
 
10754
                goto done;
 
10755
 
 
10756
found_end_int_subset:
 
10757
                xmlParseInternalSubset(ctxt);
 
10758
                ctxt->inSubset = 2;
 
10759
                if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
10760
                    (ctxt->sax->externalSubset != NULL))
 
10761
                    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 
10762
                            ctxt->extSubSystem, ctxt->extSubURI);
 
10763
                ctxt->inSubset = 0;
 
10764
                xmlCleanSpecialAttr(ctxt);
 
10765
                ctxt->instate = XML_PARSER_PROLOG;
 
10766
                ctxt->checkIndex = 0;
 
10767
#ifdef DEBUG_PUSH
 
10768
                xmlGenericError(xmlGenericErrorContext,
 
10769
                        "PP: entering PROLOG\n");
 
10770
#endif
 
10771
                break;
 
10772
            }
 
10773
            case XML_PARSER_COMMENT:
 
10774
                xmlGenericError(xmlGenericErrorContext,
 
10775
                        "PP: internal error, state == COMMENT\n");
 
10776
                ctxt->instate = XML_PARSER_CONTENT;
 
10777
#ifdef DEBUG_PUSH
 
10778
                xmlGenericError(xmlGenericErrorContext,
 
10779
                        "PP: entering CONTENT\n");
 
10780
#endif
 
10781
                break;
 
10782
            case XML_PARSER_IGNORE:
 
10783
                xmlGenericError(xmlGenericErrorContext,
 
10784
                        "PP: internal error, state == IGNORE");
 
10785
                ctxt->instate = XML_PARSER_DTD;
 
10786
#ifdef DEBUG_PUSH
 
10787
                xmlGenericError(xmlGenericErrorContext,
 
10788
                        "PP: entering DTD\n");
 
10789
#endif
 
10790
                break;
 
10791
            case XML_PARSER_PI:
 
10792
                xmlGenericError(xmlGenericErrorContext,
 
10793
                        "PP: internal error, state == PI\n");
 
10794
                ctxt->instate = XML_PARSER_CONTENT;
 
10795
#ifdef DEBUG_PUSH
 
10796
                xmlGenericError(xmlGenericErrorContext,
 
10797
                        "PP: entering CONTENT\n");
 
10798
#endif
 
10799
                break;
 
10800
            case XML_PARSER_ENTITY_DECL:
 
10801
                xmlGenericError(xmlGenericErrorContext,
 
10802
                        "PP: internal error, state == ENTITY_DECL\n");
 
10803
                ctxt->instate = XML_PARSER_DTD;
 
10804
#ifdef DEBUG_PUSH
 
10805
                xmlGenericError(xmlGenericErrorContext,
 
10806
                        "PP: entering DTD\n");
 
10807
#endif
 
10808
                break;
 
10809
            case XML_PARSER_ENTITY_VALUE:
 
10810
                xmlGenericError(xmlGenericErrorContext,
 
10811
                        "PP: internal error, state == ENTITY_VALUE\n");
 
10812
                ctxt->instate = XML_PARSER_CONTENT;
 
10813
#ifdef DEBUG_PUSH
 
10814
                xmlGenericError(xmlGenericErrorContext,
 
10815
                        "PP: entering DTD\n");
 
10816
#endif
 
10817
                break;
 
10818
            case XML_PARSER_ATTRIBUTE_VALUE:
 
10819
                xmlGenericError(xmlGenericErrorContext,
 
10820
                        "PP: internal error, state == ATTRIBUTE_VALUE\n");
 
10821
                ctxt->instate = XML_PARSER_START_TAG;
 
10822
#ifdef DEBUG_PUSH
 
10823
                xmlGenericError(xmlGenericErrorContext,
 
10824
                        "PP: entering START_TAG\n");
 
10825
#endif
 
10826
                break;
 
10827
            case XML_PARSER_SYSTEM_LITERAL:
 
10828
                xmlGenericError(xmlGenericErrorContext,
 
10829
                        "PP: internal error, state == SYSTEM_LITERAL\n");
 
10830
                ctxt->instate = XML_PARSER_START_TAG;
 
10831
#ifdef DEBUG_PUSH
 
10832
                xmlGenericError(xmlGenericErrorContext,
 
10833
                        "PP: entering START_TAG\n");
 
10834
#endif
 
10835
                break;
 
10836
            case XML_PARSER_PUBLIC_LITERAL:
 
10837
                xmlGenericError(xmlGenericErrorContext,
 
10838
                        "PP: internal error, state == PUBLIC_LITERAL\n");
 
10839
                ctxt->instate = XML_PARSER_START_TAG;
 
10840
#ifdef DEBUG_PUSH
 
10841
                xmlGenericError(xmlGenericErrorContext,
 
10842
                        "PP: entering START_TAG\n");
 
10843
#endif
 
10844
                break;
 
10845
        }
 
10846
    }
 
10847
done:    
 
10848
#ifdef DEBUG_PUSH
 
10849
    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
 
10850
#endif
 
10851
    return(ret);
 
10852
encoding_error:
 
10853
    {
 
10854
        char buffer[150];
 
10855
 
 
10856
        snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
 
10857
                        ctxt->input->cur[0], ctxt->input->cur[1],
 
10858
                        ctxt->input->cur[2], ctxt->input->cur[3]);
 
10859
        __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
 
10860
                     "Input is not proper UTF-8, indicate encoding !\n%s",
 
10861
                     BAD_CAST buffer, NULL);
 
10862
    }
 
10863
    return(0);
 
10864
}
 
10865
 
 
10866
/**
 
10867
 * xmlParseChunk:
 
10868
 * @ctxt:  an XML parser context
 
10869
 * @chunk:  an char array
 
10870
 * @size:  the size in byte of the chunk
 
10871
 * @terminate:  last chunk indicator
 
10872
 *
 
10873
 * Parse a Chunk of memory
 
10874
 *
 
10875
 * Returns zero if no error, the xmlParserErrors otherwise.
 
10876
 */
 
10877
int
 
10878
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
 
10879
              int terminate) {
 
10880
    int end_in_lf = 0;
 
10881
 
 
10882
    if (ctxt == NULL)
 
10883
        return(XML_ERR_INTERNAL_ERROR);
 
10884
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
10885
        return(ctxt->errNo);
 
10886
    if (ctxt->instate == XML_PARSER_START)
 
10887
        xmlDetectSAX2(ctxt);
 
10888
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
 
10889
        (chunk[size - 1] == '\r')) {
 
10890
        end_in_lf = 1;
 
10891
        size--;
 
10892
    }
 
10893
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
 
10894
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
 
10895
        int base = ctxt->input->base - ctxt->input->buf->buffer->content;
 
10896
        int cur = ctxt->input->cur - ctxt->input->base;
 
10897
        int res;
 
10898
        
 
10899
        res =xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
10900
        if (res < 0) {
 
10901
            ctxt->errNo = XML_PARSER_EOF;
 
10902
            ctxt->disableSAX = 1;
 
10903
            return (XML_PARSER_EOF);
 
10904
        }
 
10905
        ctxt->input->base = ctxt->input->buf->buffer->content + base;
 
10906
        ctxt->input->cur = ctxt->input->base + cur;
 
10907
        ctxt->input->end =
 
10908
            &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
 
10909
#ifdef DEBUG_PUSH
 
10910
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
10911
#endif
 
10912
 
 
10913
    } else if (ctxt->instate != XML_PARSER_EOF) {
 
10914
        if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
 
10915
            xmlParserInputBufferPtr in = ctxt->input->buf;
 
10916
            if ((in->encoder != NULL) && (in->buffer != NULL) &&
 
10917
                    (in->raw != NULL)) {
 
10918
                int nbchars;
 
10919
                    
 
10920
                nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
 
10921
                if (nbchars < 0) {
 
10922
                    /* TODO 2.6.0 */
 
10923
                    xmlGenericError(xmlGenericErrorContext,
 
10924
                                    "xmlParseChunk: encoder error\n");
 
10925
                    return(XML_ERR_INVALID_ENCODING);
 
10926
                }
 
10927
            }
 
10928
        }
 
10929
    }
 
10930
    xmlParseTryOrFinish(ctxt, terminate);
 
10931
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
 
10932
        (ctxt->input->buf != NULL)) {
 
10933
        xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
 
10934
    }
 
10935
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
10936
        return(ctxt->errNo);
 
10937
    if (terminate) {
 
10938
        /*
 
10939
         * Check for termination
 
10940
         */
 
10941
        int avail = 0;
 
10942
 
 
10943
        if (ctxt->input != NULL) {
 
10944
            if (ctxt->input->buf == NULL)
 
10945
                avail = ctxt->input->length -
 
10946
                        (ctxt->input->cur - ctxt->input->base);
 
10947
            else
 
10948
                avail = ctxt->input->buf->buffer->use -
 
10949
                        (ctxt->input->cur - ctxt->input->base);
 
10950
        }
 
10951
                            
 
10952
        if ((ctxt->instate != XML_PARSER_EOF) &&
 
10953
            (ctxt->instate != XML_PARSER_EPILOG)) {
 
10954
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
10955
        } 
 
10956
        if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) {
 
10957
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
10958
        }
 
10959
        if (ctxt->instate != XML_PARSER_EOF) {
 
10960
            if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10961
                ctxt->sax->endDocument(ctxt->userData);
 
10962
        }
 
10963
        ctxt->instate = XML_PARSER_EOF;
 
10964
    }
 
10965
    return((xmlParserErrors) ctxt->errNo);            
 
10966
}
 
10967
 
 
10968
/************************************************************************
 
10969
 *                                                                      *
 
10970
 *              I/O front end functions to the parser                   *
 
10971
 *                                                                      *
 
10972
 ************************************************************************/
 
10973
 
 
10974
/**
 
10975
 * xmlCreatePushParserCtxt:
 
10976
 * @sax:  a SAX handler
 
10977
 * @user_data:  The user data returned on SAX callbacks
 
10978
 * @chunk:  a pointer to an array of chars
 
10979
 * @size:  number of chars in the array
 
10980
 * @filename:  an optional file name or URI
 
10981
 *
 
10982
 * Create a parser context for using the XML parser in push mode.
 
10983
 * If @buffer and @size are non-NULL, the data is used to detect
 
10984
 * the encoding.  The remaining characters will be parsed so they
 
10985
 * don't need to be fed in again through xmlParseChunk.
 
10986
 * To allow content encoding detection, @size should be >= 4
 
10987
 * The value of @filename is used for fetching external entities
 
10988
 * and error/warning reports.
 
10989
 *
 
10990
 * Returns the new parser context or NULL
 
10991
 */
 
10992
 
 
10993
xmlParserCtxtPtr
 
10994
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, 
 
10995
                        const char *chunk, int size, const char *filename) {
 
10996
    xmlParserCtxtPtr ctxt;
 
10997
    xmlParserInputPtr inputStream;
 
10998
    xmlParserInputBufferPtr buf;
 
10999
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
11000
 
 
11001
    /*
 
11002
     * plug some encoding conversion routines
 
11003
     */
 
11004
    if ((chunk != NULL) && (size >= 4))
 
11005
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
 
11006
 
 
11007
    buf = xmlAllocParserInputBuffer(enc);
 
11008
    if (buf == NULL) return(NULL);
 
11009
 
 
11010
    ctxt = xmlNewParserCtxt();
 
11011
    if (ctxt == NULL) {
 
11012
        xmlErrMemory(NULL, "creating parser: out of memory\n");
 
11013
        xmlFreeParserInputBuffer(buf);
 
11014
        return(NULL);
 
11015
    }
 
11016
    ctxt->dictNames = 1;
 
11017
    ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
 
11018
    if (ctxt->pushTab == NULL) {
 
11019
        xmlErrMemory(ctxt, NULL);
 
11020
        xmlFreeParserInputBuffer(buf);
 
11021
        xmlFreeParserCtxt(ctxt);
 
11022
        return(NULL);
 
11023
    }
 
11024
    if (sax != NULL) {
 
11025
#ifdef LIBXML_SAX1_ENABLED
 
11026
        if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
11027
#endif /* LIBXML_SAX1_ENABLED */
 
11028
            xmlFree(ctxt->sax);
 
11029
        ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 
11030
        if (ctxt->sax == NULL) {
 
11031
            xmlErrMemory(ctxt, NULL);
 
11032
            xmlFreeParserInputBuffer(buf);
 
11033
            xmlFreeParserCtxt(ctxt);
 
11034
            return(NULL);
 
11035
        }
 
11036
        memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
 
11037
        if (sax->initialized == XML_SAX2_MAGIC)
 
11038
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
 
11039
        else
 
11040
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
 
11041
        if (user_data != NULL)
 
11042
            ctxt->userData = user_data;
 
11043
    }   
 
11044
    if (filename == NULL) {
 
11045
        ctxt->directory = NULL;
 
11046
    } else {
 
11047
        ctxt->directory = xmlParserGetDirectory(filename);
 
11048
    }
 
11049
 
 
11050
    inputStream = xmlNewInputStream(ctxt);
 
11051
    if (inputStream == NULL) {
 
11052
        xmlFreeParserCtxt(ctxt);
 
11053
        xmlFreeParserInputBuffer(buf);
 
11054
        return(NULL);
 
11055
    }
 
11056
 
 
11057
    if (filename == NULL)
 
11058
        inputStream->filename = NULL;
 
11059
    else {
 
11060
        inputStream->filename = (char *)
 
11061
            xmlCanonicPath((const xmlChar *) filename);
 
11062
        if (inputStream->filename == NULL) {
 
11063
            xmlFreeParserCtxt(ctxt);
 
11064
            xmlFreeParserInputBuffer(buf);
 
11065
            return(NULL);
 
11066
        }
 
11067
    }
 
11068
    inputStream->buf = buf;
 
11069
    inputStream->base = inputStream->buf->buffer->content;
 
11070
    inputStream->cur = inputStream->buf->buffer->content;
 
11071
    inputStream->end = 
 
11072
        &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
 
11073
 
 
11074
    inputPush(ctxt, inputStream);
 
11075
 
 
11076
    /*
 
11077
     * If the caller didn't provide an initial 'chunk' for determining
 
11078
     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
 
11079
     * that it can be automatically determined later
 
11080
     */
 
11081
    if ((size == 0) || (chunk == NULL)) {
 
11082
        ctxt->charset = XML_CHAR_ENCODING_NONE;
 
11083
    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
 
11084
        int base = ctxt->input->base - ctxt->input->buf->buffer->content;
 
11085
        int cur = ctxt->input->cur - ctxt->input->base;
 
11086
 
 
11087
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);              
 
11088
 
 
11089
        ctxt->input->base = ctxt->input->buf->buffer->content + base;
 
11090
        ctxt->input->cur = ctxt->input->base + cur;
 
11091
        ctxt->input->end =
 
11092
            &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
 
11093
#ifdef DEBUG_PUSH
 
11094
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
11095
#endif
 
11096
    }
 
11097
 
 
11098
    if (enc != XML_CHAR_ENCODING_NONE) {
 
11099
        xmlSwitchEncoding(ctxt, enc);
 
11100
    }
 
11101
 
 
11102
    return(ctxt);
 
11103
}
 
11104
#endif /* LIBXML_PUSH_ENABLED */
 
11105
 
 
11106
/**
 
11107
 * xmlStopParser:
 
11108
 * @ctxt:  an XML parser context
 
11109
 *
 
11110
 * Blocks further parser processing
 
11111
 */
 
11112
void           
 
11113
xmlStopParser(xmlParserCtxtPtr ctxt) {
 
11114
    if (ctxt == NULL)
 
11115
        return;
 
11116
    ctxt->instate = XML_PARSER_EOF;
 
11117
    ctxt->disableSAX = 1;
 
11118
    if (ctxt->input != NULL) {
 
11119
        ctxt->input->cur = BAD_CAST"";
 
11120
        ctxt->input->base = ctxt->input->cur;
 
11121
    }
 
11122
}
 
11123
 
 
11124
/**
 
11125
 * xmlCreateIOParserCtxt:
 
11126
 * @sax:  a SAX handler
 
11127
 * @user_data:  The user data returned on SAX callbacks
 
11128
 * @ioread:  an I/O read function
 
11129
 * @ioclose:  an I/O close function
 
11130
 * @ioctx:  an I/O handler
 
11131
 * @enc:  the charset encoding if known
 
11132
 *
 
11133
 * Create a parser context for using the XML parser with an existing
 
11134
 * I/O stream
 
11135
 *
 
11136
 * Returns the new parser context or NULL
 
11137
 */
 
11138
xmlParserCtxtPtr
 
11139
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
 
11140
        xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
 
11141
        void *ioctx, xmlCharEncoding enc) {
 
11142
    xmlParserCtxtPtr ctxt;
 
11143
    xmlParserInputPtr inputStream;
 
11144
    xmlParserInputBufferPtr buf;
 
11145
    
 
11146
    if (ioread == NULL) return(NULL);
 
11147
 
 
11148
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
 
11149
    if (buf == NULL) return(NULL);
 
11150
 
 
11151
    ctxt = xmlNewParserCtxt();
 
11152
    if (ctxt == NULL) {
 
11153
        xmlFreeParserInputBuffer(buf);
 
11154
        return(NULL);
 
11155
    }
 
11156
    if (sax != NULL) {
 
11157
#ifdef LIBXML_SAX1_ENABLED
 
11158
        if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
11159
#endif /* LIBXML_SAX1_ENABLED */
 
11160
            xmlFree(ctxt->sax);
 
11161
        ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 
11162
        if (ctxt->sax == NULL) {
 
11163
            xmlErrMemory(ctxt, NULL);
 
11164
            xmlFreeParserCtxt(ctxt);
 
11165
            return(NULL);
 
11166
        }
 
11167
        memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
 
11168
        if (sax->initialized == XML_SAX2_MAGIC)
 
11169
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
 
11170
        else
 
11171
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
 
11172
        if (user_data != NULL)
 
11173
            ctxt->userData = user_data;
 
11174
    }   
 
11175
 
 
11176
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
 
11177
    if (inputStream == NULL) {
 
11178
        xmlFreeParserCtxt(ctxt);
 
11179
        return(NULL);
 
11180
    }
 
11181
    inputPush(ctxt, inputStream);
 
11182
 
 
11183
    return(ctxt);
 
11184
}
 
11185
 
 
11186
#ifdef LIBXML_VALID_ENABLED
 
11187
/************************************************************************
 
11188
 *                                                                      *
 
11189
 *              Front ends when parsing a DTD                           *
 
11190
 *                                                                      *
 
11191
 ************************************************************************/
 
11192
 
 
11193
/**
 
11194
 * xmlIOParseDTD:
 
11195
 * @sax:  the SAX handler block or NULL
 
11196
 * @input:  an Input Buffer
 
11197
 * @enc:  the charset encoding if known
 
11198
 *
 
11199
 * Load and parse a DTD
 
11200
 * 
 
11201
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
11202
 * @input will be freed by the function in any case.
 
11203
 */
 
11204
 
 
11205
xmlDtdPtr
 
11206
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
 
11207
              xmlCharEncoding enc) {
 
11208
    xmlDtdPtr ret = NULL;
 
11209
    xmlParserCtxtPtr ctxt;
 
11210
    xmlParserInputPtr pinput = NULL;
 
11211
    xmlChar start[4];
 
11212
 
 
11213
    if (input == NULL)
 
11214
        return(NULL);
 
11215
 
 
11216
    ctxt = xmlNewParserCtxt();
 
11217
    if (ctxt == NULL) {
 
11218
        xmlFreeParserInputBuffer(input);
 
11219
        return(NULL);
 
11220
    }
 
11221
 
 
11222
    /*
 
11223
     * Set-up the SAX context
 
11224
     */
 
11225
    if (sax != NULL) { 
 
11226
        if (ctxt->sax != NULL)
 
11227
            xmlFree(ctxt->sax);
 
11228
        ctxt->sax = sax;
 
11229
        ctxt->userData = ctxt;
 
11230
    }
 
11231
    xmlDetectSAX2(ctxt);
 
11232
 
 
11233
    /*
 
11234
     * generate a parser input from the I/O handler
 
11235
     */
 
11236
 
 
11237
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
11238
    if (pinput == NULL) {
 
11239
        if (sax != NULL) ctxt->sax = NULL;
 
11240
        xmlFreeParserInputBuffer(input);
 
11241
        xmlFreeParserCtxt(ctxt);
 
11242
        return(NULL);
 
11243
    }
 
11244
 
 
11245
    /*
 
11246
     * plug some encoding conversion routines here.
 
11247
     */
 
11248
    xmlPushInput(ctxt, pinput);
 
11249
    if (enc != XML_CHAR_ENCODING_NONE) {
 
11250
        xmlSwitchEncoding(ctxt, enc);
 
11251
    }
 
11252
 
 
11253
    pinput->filename = NULL;
 
11254
    pinput->line = 1;
 
11255
    pinput->col = 1;
 
11256
    pinput->base = ctxt->input->cur;
 
11257
    pinput->cur = ctxt->input->cur;
 
11258
    pinput->free = NULL;
 
11259
 
 
11260
    /*
 
11261
     * let's parse that entity knowing it's an external subset.
 
11262
     */
 
11263
    ctxt->inSubset = 2;
 
11264
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
11265
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 
11266
                                       BAD_CAST "none", BAD_CAST "none");
 
11267
 
 
11268
    if ((enc == XML_CHAR_ENCODING_NONE) &&
 
11269
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
 
11270
        /* 
 
11271
         * Get the 4 first bytes and decode the charset
 
11272
         * if enc != XML_CHAR_ENCODING_NONE
 
11273
         * plug some encoding conversion routines.
 
11274
         */
 
11275
        start[0] = RAW;
 
11276
        start[1] = NXT(1);
 
11277
        start[2] = NXT(2);
 
11278
        start[3] = NXT(3);
 
11279
        enc = xmlDetectCharEncoding(start, 4);
 
11280
        if (enc != XML_CHAR_ENCODING_NONE) {
 
11281
            xmlSwitchEncoding(ctxt, enc);
 
11282
        }
 
11283
    }
 
11284
 
 
11285
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
 
11286
 
 
11287
    if (ctxt->myDoc != NULL) {
 
11288
        if (ctxt->wellFormed) {
 
11289
            ret = ctxt->myDoc->extSubset;
 
11290
            ctxt->myDoc->extSubset = NULL;
 
11291
            if (ret != NULL) {
 
11292
                xmlNodePtr tmp;
 
11293
 
 
11294
                ret->doc = NULL;
 
11295
                tmp = ret->children;
 
11296
                while (tmp != NULL) {
 
11297
                    tmp->doc = NULL;
 
11298
                    tmp = tmp->next;
 
11299
                }
 
11300
            }
 
11301
        } else {
 
11302
            ret = NULL;
 
11303
        }
 
11304
        xmlFreeDoc(ctxt->myDoc);
 
11305
        ctxt->myDoc = NULL;
 
11306
    }
 
11307
    if (sax != NULL) ctxt->sax = NULL;
 
11308
    xmlFreeParserCtxt(ctxt);
 
11309
    
 
11310
    return(ret);
 
11311
}
 
11312
 
 
11313
/**
 
11314
 * xmlSAXParseDTD:
 
11315
 * @sax:  the SAX handler block
 
11316
 * @ExternalID:  a NAME* containing the External ID of the DTD
 
11317
 * @SystemID:  a NAME* containing the URL to the DTD
 
11318
 *
 
11319
 * Load and parse an external subset.
 
11320
 * 
 
11321
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
11322
 */
 
11323
 
 
11324
xmlDtdPtr
 
11325
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
 
11326
                          const xmlChar *SystemID) {
 
11327
    xmlDtdPtr ret = NULL;
 
11328
    xmlParserCtxtPtr ctxt;
 
11329
    xmlParserInputPtr input = NULL;
 
11330
    xmlCharEncoding enc;
 
11331
    xmlChar* systemIdCanonic;
 
11332
 
 
11333
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
 
11334
 
 
11335
    ctxt = xmlNewParserCtxt();
 
11336
    if (ctxt == NULL) {
 
11337
        return(NULL);
 
11338
    }
 
11339
 
 
11340
    /*
 
11341
     * Set-up the SAX context
 
11342
     */
 
11343
    if (sax != NULL) { 
 
11344
        if (ctxt->sax != NULL)
 
11345
            xmlFree(ctxt->sax);
 
11346
        ctxt->sax = sax;
 
11347
        ctxt->userData = ctxt;
 
11348
    }
 
11349
    
 
11350
    /*
 
11351
     * Canonicalise the system ID
 
11352
     */
 
11353
    systemIdCanonic = xmlCanonicPath(SystemID);
 
11354
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
 
11355
        xmlFreeParserCtxt(ctxt);
 
11356
        return(NULL);
 
11357
    }
 
11358
 
 
11359
    /*
 
11360
     * Ask the Entity resolver to load the damn thing
 
11361
     */
 
11362
 
 
11363
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
 
11364
        input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
 
11365
                                         systemIdCanonic);
 
11366
    if (input == NULL) {
 
11367
        if (sax != NULL) ctxt->sax = NULL;
 
11368
        xmlFreeParserCtxt(ctxt);
 
11369
        if (systemIdCanonic != NULL)
 
11370
            xmlFree(systemIdCanonic);
 
11371
        return(NULL);
 
11372
    }
 
11373
 
 
11374
    /*
 
11375
     * plug some encoding conversion routines here.
 
11376
     */
 
11377
    xmlPushInput(ctxt, input);
 
11378
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
11379
        enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
 
11380
        xmlSwitchEncoding(ctxt, enc);
 
11381
    }
 
11382
 
 
11383
    if (input->filename == NULL)
 
11384
        input->filename = (char *) systemIdCanonic;
 
11385
    else
 
11386
        xmlFree(systemIdCanonic);
 
11387
    input->line = 1;
 
11388
    input->col = 1;
 
11389
    input->base = ctxt->input->cur;
 
11390
    input->cur = ctxt->input->cur;
 
11391
    input->free = NULL;
 
11392
 
 
11393
    /*
 
11394
     * let's parse that entity knowing it's an external subset.
 
11395
     */
 
11396
    ctxt->inSubset = 2;
 
11397
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
11398
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 
11399
                                       ExternalID, SystemID);
 
11400
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
 
11401
 
 
11402
    if (ctxt->myDoc != NULL) {
 
11403
        if (ctxt->wellFormed) {
 
11404
            ret = ctxt->myDoc->extSubset;
 
11405
            ctxt->myDoc->extSubset = NULL;
 
11406
            if (ret != NULL) {
 
11407
                xmlNodePtr tmp;
 
11408
 
 
11409
                ret->doc = NULL;
 
11410
                tmp = ret->children;
 
11411
                while (tmp != NULL) {
 
11412
                    tmp->doc = NULL;
 
11413
                    tmp = tmp->next;
 
11414
                }
 
11415
            }
 
11416
        } else {
 
11417
            ret = NULL;
 
11418
        }
 
11419
        xmlFreeDoc(ctxt->myDoc);
 
11420
        ctxt->myDoc = NULL;
 
11421
    }
 
11422
    if (sax != NULL) ctxt->sax = NULL;
 
11423
    xmlFreeParserCtxt(ctxt);
 
11424
    
 
11425
    return(ret);
 
11426
}
 
11427
 
 
11428
 
 
11429
/**
 
11430
 * xmlParseDTD:
 
11431
 * @ExternalID:  a NAME* containing the External ID of the DTD
 
11432
 * @SystemID:  a NAME* containing the URL to the DTD
 
11433
 *
 
11434
 * Load and parse an external subset.
 
11435
 * 
 
11436
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
11437
 */
 
11438
 
 
11439
xmlDtdPtr
 
11440
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
 
11441
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
 
11442
}
 
11443
#endif /* LIBXML_VALID_ENABLED */
 
11444
 
 
11445
/************************************************************************
 
11446
 *                                                                      *
 
11447
 *              Front ends when parsing an Entity                       *
 
11448
 *                                                                      *
 
11449
 ************************************************************************/
 
11450
 
 
11451
/**
 
11452
 * xmlParseCtxtExternalEntity:
 
11453
 * @ctx:  the existing parsing context
 
11454
 * @URL:  the URL for the entity to load
 
11455
 * @ID:  the System ID for the entity to load
 
11456
 * @lst:  the return value for the set of parsed nodes
 
11457
 *
 
11458
 * Parse an external general entity within an existing parsing context
 
11459
 * An external general parsed entity is well-formed if it matches the
 
11460
 * production labeled extParsedEnt.
 
11461
 *
 
11462
 * [78] extParsedEnt ::= TextDecl? content
 
11463
 *
 
11464
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
11465
 *    the parser error code otherwise
 
11466
 */
 
11467
 
 
11468
int
 
11469
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
 
11470
                       const xmlChar *ID, xmlNodePtr *lst) {
 
11471
    xmlParserCtxtPtr ctxt;
 
11472
    xmlDocPtr newDoc;
 
11473
    xmlNodePtr newRoot;
 
11474
    xmlSAXHandlerPtr oldsax = NULL;
 
11475
    int ret = 0;
 
11476
    xmlChar start[4];
 
11477
    xmlCharEncoding enc;
 
11478
    xmlParserInputPtr inputStream;
 
11479
    char *directory = NULL;
 
11480
 
 
11481
    if (ctx == NULL) return(-1);
 
11482
 
 
11483
    if (ctx->depth > 40) {
 
11484
        return(XML_ERR_ENTITY_LOOP);
 
11485
    }
 
11486
 
 
11487
    if (lst != NULL)
 
11488
        *lst = NULL;
 
11489
    if ((URL == NULL) && (ID == NULL))
 
11490
        return(-1);
 
11491
    if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
 
11492
        return(-1);
 
11493
 
 
11494
    ctxt = xmlNewParserCtxt();
 
11495
    if (ctxt == NULL) {
 
11496
        return(-1);
 
11497
    }
 
11498
    
 
11499
    ctxt->userData = ctxt;
 
11500
    ctxt->_private = ctx->_private;
 
11501
    
 
11502
    inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
 
11503
    if (inputStream == NULL) {
 
11504
        xmlFreeParserCtxt(ctxt);
 
11505
        return(-1);
 
11506
    }
 
11507
 
 
11508
    inputPush(ctxt, inputStream);
 
11509
 
 
11510
    if ((ctxt->directory == NULL) && (directory == NULL))
 
11511
        directory = xmlParserGetDirectory((char *)URL);
 
11512
    if ((ctxt->directory == NULL) && (directory != NULL))
 
11513
        ctxt->directory = directory;
 
11514
    
 
11515
    oldsax = ctxt->sax;
 
11516
    ctxt->sax = ctx->sax;
 
11517
    xmlDetectSAX2(ctxt);
 
11518
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
11519
    if (newDoc == NULL) {
 
11520
        xmlFreeParserCtxt(ctxt);
 
11521
        return(-1);
 
11522
    }
 
11523
    if (ctx->myDoc->dict) {
 
11524
        newDoc->dict = ctx->myDoc->dict;
 
11525
        xmlDictReference(newDoc->dict);
 
11526
    }
 
11527
    if (ctx->myDoc != NULL) {
 
11528
        newDoc->intSubset = ctx->myDoc->intSubset;
 
11529
        newDoc->extSubset = ctx->myDoc->extSubset;
 
11530
    }
 
11531
    if (ctx->myDoc->URL != NULL) {
 
11532
        newDoc->URL = xmlStrdup(ctx->myDoc->URL);
 
11533
    }
 
11534
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
11535
    if (newRoot == NULL) {
 
11536
        ctxt->sax = oldsax;
 
11537
        xmlFreeParserCtxt(ctxt);
 
11538
        newDoc->intSubset = NULL;
 
11539
        newDoc->extSubset = NULL;
 
11540
        xmlFreeDoc(newDoc);
 
11541
        return(-1);
 
11542
    }
 
11543
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
11544
    nodePush(ctxt, newDoc->children);
 
11545
    if (ctx->myDoc == NULL) {
 
11546
        ctxt->myDoc = newDoc;
 
11547
    } else {
 
11548
        ctxt->myDoc = ctx->myDoc;
 
11549
        newDoc->children->doc = ctx->myDoc;
 
11550
    }
 
11551
 
 
11552
    /* 
 
11553
     * Get the 4 first bytes and decode the charset
 
11554
     * if enc != XML_CHAR_ENCODING_NONE
 
11555
     * plug some encoding conversion routines.
 
11556
     */
 
11557
    GROW
 
11558
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
11559
        start[0] = RAW;
 
11560
        start[1] = NXT(1);
 
11561
        start[2] = NXT(2);
 
11562
        start[3] = NXT(3);
 
11563
        enc = xmlDetectCharEncoding(start, 4);
 
11564
        if (enc != XML_CHAR_ENCODING_NONE) {
 
11565
            xmlSwitchEncoding(ctxt, enc);
 
11566
        }
 
11567
    }
 
11568
 
 
11569
    /*
 
11570
     * Parse a possible text declaration first
 
11571
     */
 
11572
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
11573
        xmlParseTextDecl(ctxt);
 
11574
    }
 
11575
 
 
11576
    /*
 
11577
     * Doing validity checking on chunk doesn't make sense
 
11578
     */
 
11579
    ctxt->instate = XML_PARSER_CONTENT;
 
11580
    ctxt->validate = ctx->validate;
 
11581
    ctxt->valid = ctx->valid;
 
11582
    ctxt->loadsubset = ctx->loadsubset;
 
11583
    ctxt->depth = ctx->depth + 1;
 
11584
    ctxt->replaceEntities = ctx->replaceEntities;
 
11585
    if (ctxt->validate) {
 
11586
        ctxt->vctxt.error = ctx->vctxt.error;
 
11587
        ctxt->vctxt.warning = ctx->vctxt.warning;
 
11588
    } else {
 
11589
        ctxt->vctxt.error = NULL;
 
11590
        ctxt->vctxt.warning = NULL;
 
11591
    }
 
11592
    ctxt->vctxt.nodeTab = NULL;
 
11593
    ctxt->vctxt.nodeNr = 0;
 
11594
    ctxt->vctxt.nodeMax = 0;
 
11595
    ctxt->vctxt.node = NULL;
 
11596
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
 
11597
    ctxt->dict = ctx->dict;
 
11598
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
11599
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
11600
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
11601
    ctxt->dictNames = ctx->dictNames;
 
11602
    ctxt->attsDefault = ctx->attsDefault;
 
11603
    ctxt->attsSpecial = ctx->attsSpecial;
 
11604
    ctxt->linenumbers = ctx->linenumbers;
 
11605
 
 
11606
    xmlParseContent(ctxt);
 
11607
   
 
11608
    ctx->validate = ctxt->validate;
 
11609
    ctx->valid = ctxt->valid;
 
11610
    if ((RAW == '<') && (NXT(1) == '/')) {
 
11611
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
11612
    } else if (RAW != 0) {
 
11613
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
11614
    }
 
11615
    if (ctxt->node != newDoc->children) {
 
11616
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
11617
    }
 
11618
 
 
11619
    if (!ctxt->wellFormed) {
 
11620
        if (ctxt->errNo == 0)
 
11621
            ret = 1;
 
11622
        else
 
11623
            ret = ctxt->errNo;
 
11624
    } else {
 
11625
        if (lst != NULL) {
 
11626
            xmlNodePtr cur;
 
11627
 
 
11628
            /*
 
11629
             * Return the newly created nodeset after unlinking it from
 
11630
             * they pseudo parent.
 
11631
             */
 
11632
            cur = newDoc->children->children;
 
11633
            *lst = cur;
 
11634
            while (cur != NULL) {
 
11635
                cur->parent = NULL;
 
11636
                cur = cur->next;
 
11637
            }
 
11638
            newDoc->children->children = NULL;
 
11639
        }
 
11640
        ret = 0;
 
11641
    }
 
11642
    ctxt->sax = oldsax;
 
11643
    ctxt->dict = NULL;
 
11644
    ctxt->attsDefault = NULL;
 
11645
    ctxt->attsSpecial = NULL;
 
11646
    xmlFreeParserCtxt(ctxt);
 
11647
    newDoc->intSubset = NULL;
 
11648
    newDoc->extSubset = NULL;
 
11649
    xmlFreeDoc(newDoc);
 
11650
    
 
11651
    return(ret);
 
11652
}
 
11653
 
 
11654
/**
 
11655
 * xmlParseExternalEntityPrivate:
 
11656
 * @doc:  the document the chunk pertains to
 
11657
 * @oldctxt:  the previous parser context if available
 
11658
 * @sax:  the SAX handler bloc (possibly NULL)
 
11659
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
11660
 * @depth:  Used for loop detection, use 0
 
11661
 * @URL:  the URL for the entity to load
 
11662
 * @ID:  the System ID for the entity to load
 
11663
 * @list:  the return value for the set of parsed nodes
 
11664
 *
 
11665
 * Private version of xmlParseExternalEntity()
 
11666
 *
 
11667
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
11668
 *    the parser error code otherwise
 
11669
 */
 
11670
 
 
11671
static xmlParserErrors
 
11672
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
 
11673
                      xmlSAXHandlerPtr sax,
 
11674
                      void *user_data, int depth, const xmlChar *URL,
 
11675
                      const xmlChar *ID, xmlNodePtr *list) {
 
11676
    xmlParserCtxtPtr ctxt;
 
11677
    xmlDocPtr newDoc;
 
11678
    xmlNodePtr newRoot;
 
11679
    xmlSAXHandlerPtr oldsax = NULL;
 
11680
    xmlParserErrors ret = XML_ERR_OK;
 
11681
    xmlChar start[4];
 
11682
    xmlCharEncoding enc;
 
11683
 
 
11684
    if (depth > 40) {
 
11685
        return(XML_ERR_ENTITY_LOOP);
 
11686
    }
 
11687
 
 
11688
 
 
11689
 
 
11690
    if (list != NULL)
 
11691
        *list = NULL;
 
11692
    if ((URL == NULL) && (ID == NULL))
 
11693
        return(XML_ERR_INTERNAL_ERROR);
 
11694
    if (doc == NULL)
 
11695
        return(XML_ERR_INTERNAL_ERROR);
 
11696
 
 
11697
 
 
11698
    ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
 
11699
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
 
11700
    ctxt->userData = ctxt;
 
11701
    if (oldctxt != NULL) {
 
11702
        ctxt->_private = oldctxt->_private;
 
11703
        ctxt->loadsubset = oldctxt->loadsubset;
 
11704
        ctxt->validate = oldctxt->validate;
 
11705
        ctxt->external = oldctxt->external;
 
11706
        ctxt->record_info = oldctxt->record_info;
 
11707
        ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
 
11708
        ctxt->node_seq.length = oldctxt->node_seq.length;
 
11709
        ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
 
11710
    } else {
 
11711
        /*
 
11712
         * Doing validity checking on chunk without context
 
11713
         * doesn't make sense
 
11714
         */
 
11715
        ctxt->_private = NULL;
 
11716
        ctxt->validate = 0;
 
11717
        ctxt->external = 2;
 
11718
        ctxt->loadsubset = 0;
 
11719
    }
 
11720
    if (sax != NULL) {
 
11721
        oldsax = ctxt->sax;
 
11722
        ctxt->sax = sax;
 
11723
        if (user_data != NULL)
 
11724
            ctxt->userData = user_data;
 
11725
    }
 
11726
    xmlDetectSAX2(ctxt);
 
11727
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
11728
    if (newDoc == NULL) {
 
11729
        ctxt->node_seq.maximum = 0;
 
11730
        ctxt->node_seq.length = 0;
 
11731
        ctxt->node_seq.buffer = NULL;
 
11732
        xmlFreeParserCtxt(ctxt);
 
11733
        return(XML_ERR_INTERNAL_ERROR);
 
11734
    }
 
11735
    newDoc->intSubset = doc->intSubset;
 
11736
    newDoc->extSubset = doc->extSubset;
 
11737
    newDoc->dict = doc->dict;
 
11738
    xmlDictReference(newDoc->dict);
 
11739
 
 
11740
    if (doc->URL != NULL) {
 
11741
        newDoc->URL = xmlStrdup(doc->URL);
 
11742
    }
 
11743
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
11744
    if (newRoot == NULL) {
 
11745
        if (sax != NULL)
 
11746
            ctxt->sax = oldsax;
 
11747
        ctxt->node_seq.maximum = 0;
 
11748
        ctxt->node_seq.length = 0;
 
11749
        ctxt->node_seq.buffer = NULL;
 
11750
        xmlFreeParserCtxt(ctxt);
 
11751
        newDoc->intSubset = NULL;
 
11752
        newDoc->extSubset = NULL;
 
11753
        xmlFreeDoc(newDoc);
 
11754
        return(XML_ERR_INTERNAL_ERROR);
 
11755
    }
 
11756
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
11757
    nodePush(ctxt, newDoc->children);
 
11758
    ctxt->myDoc = doc;
 
11759
    newRoot->doc = doc;
 
11760
 
 
11761
    /* 
 
11762
     * Get the 4 first bytes and decode the charset
 
11763
     * if enc != XML_CHAR_ENCODING_NONE
 
11764
     * plug some encoding conversion routines.
 
11765
     */
 
11766
    GROW;
 
11767
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
11768
        start[0] = RAW;
 
11769
        start[1] = NXT(1);
 
11770
        start[2] = NXT(2);
 
11771
        start[3] = NXT(3);
 
11772
        enc = xmlDetectCharEncoding(start, 4);
 
11773
        if (enc != XML_CHAR_ENCODING_NONE) {
 
11774
            xmlSwitchEncoding(ctxt, enc);
 
11775
        }
 
11776
    }
 
11777
 
 
11778
    /*
 
11779
     * Parse a possible text declaration first
 
11780
     */
 
11781
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
11782
        xmlParseTextDecl(ctxt);
 
11783
    }
 
11784
 
 
11785
    ctxt->instate = XML_PARSER_CONTENT;
 
11786
    ctxt->depth = depth;
 
11787
 
 
11788
    xmlParseContent(ctxt);
 
11789
   
 
11790
    if ((RAW == '<') && (NXT(1) == '/')) {
 
11791
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
11792
    } else if (RAW != 0) {
 
11793
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
11794
    }
 
11795
    if (ctxt->node != newDoc->children) {
 
11796
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
11797
    }
 
11798
 
 
11799
    if (!ctxt->wellFormed) {
 
11800
        if (ctxt->errNo == 0)
 
11801
            ret = XML_ERR_INTERNAL_ERROR;
 
11802
        else
 
11803
            ret = (xmlParserErrors)ctxt->errNo;
 
11804
    } else {
 
11805
        if (list != NULL) {
 
11806
            xmlNodePtr cur;
 
11807
 
 
11808
            /*
 
11809
             * Return the newly created nodeset after unlinking it from
 
11810
             * they pseudo parent.
 
11811
             */
 
11812
            cur = newDoc->children->children;
 
11813
            *list = cur;
 
11814
            while (cur != NULL) {
 
11815
                cur->parent = NULL;
 
11816
                cur = cur->next;
 
11817
            }
 
11818
            newDoc->children->children = NULL;
 
11819
        }
 
11820
        ret = XML_ERR_OK;
 
11821
    }
 
11822
    if (sax != NULL) 
 
11823
        ctxt->sax = oldsax;
 
11824
    oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
 
11825
    oldctxt->node_seq.length = ctxt->node_seq.length;
 
11826
    oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
 
11827
    ctxt->node_seq.maximum = 0;
 
11828
    ctxt->node_seq.length = 0;
 
11829
    ctxt->node_seq.buffer = NULL;
 
11830
    xmlFreeParserCtxt(ctxt);
 
11831
    newDoc->intSubset = NULL;
 
11832
    newDoc->extSubset = NULL;
 
11833
    xmlFreeDoc(newDoc);
 
11834
    
 
11835
    return(ret);
 
11836
}
 
11837
 
 
11838
#ifdef LIBXML_SAX1_ENABLED
 
11839
/**
 
11840
 * xmlParseExternalEntity:
 
11841
 * @doc:  the document the chunk pertains to
 
11842
 * @sax:  the SAX handler bloc (possibly NULL)
 
11843
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
11844
 * @depth:  Used for loop detection, use 0
 
11845
 * @URL:  the URL for the entity to load
 
11846
 * @ID:  the System ID for the entity to load
 
11847
 * @lst:  the return value for the set of parsed nodes
 
11848
 *
 
11849
 * Parse an external general entity
 
11850
 * An external general parsed entity is well-formed if it matches the
 
11851
 * production labeled extParsedEnt.
 
11852
 *
 
11853
 * [78] extParsedEnt ::= TextDecl? content
 
11854
 *
 
11855
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
11856
 *    the parser error code otherwise
 
11857
 */
 
11858
 
 
11859
int
 
11860
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
 
11861
          int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
 
11862
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
 
11863
                                       ID, lst));
 
11864
}
 
11865
 
 
11866
/**
 
11867
 * xmlParseBalancedChunkMemory:
 
11868
 * @doc:  the document the chunk pertains to
 
11869
 * @sax:  the SAX handler bloc (possibly NULL)
 
11870
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
11871
 * @depth:  Used for loop detection, use 0
 
11872
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
11873
 * @lst:  the return value for the set of parsed nodes
 
11874
 *
 
11875
 * Parse a well-balanced chunk of an XML document
 
11876
 * called by the parser
 
11877
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
11878
 * the content production in the XML grammar:
 
11879
 *
 
11880
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
11881
 *
 
11882
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
 
11883
 *    the parser error code otherwise
 
11884
 */
 
11885
 
 
11886
int
 
11887
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
 
11888
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
 
11889
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
 
11890
                                                depth, string, lst, 0 );
 
11891
}
 
11892
#endif /* LIBXML_SAX1_ENABLED */
 
11893
 
 
11894
/**
 
11895
 * xmlParseBalancedChunkMemoryInternal:
 
11896
 * @oldctxt:  the existing parsing context
 
11897
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
11898
 * @user_data:  the user data field for the parser context
 
11899
 * @lst:  the return value for the set of parsed nodes
 
11900
 *
 
11901
 *
 
11902
 * Parse a well-balanced chunk of an XML document
 
11903
 * called by the parser
 
11904
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
11905
 * the content production in the XML grammar:
 
11906
 *
 
11907
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
11908
 *
 
11909
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
 
11910
 * error code otherwise
 
11911
 *    
 
11912
 * In case recover is set to 1, the nodelist will not be empty even if
 
11913
 * the parsed chunk is not well balanced. 
 
11914
 */
 
11915
static xmlParserErrors
 
11916
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 
11917
        const xmlChar *string, void *user_data, xmlNodePtr *lst) {
 
11918
    xmlParserCtxtPtr ctxt;
 
11919
    xmlDocPtr newDoc = NULL;
 
11920
    xmlNodePtr newRoot;
 
11921
    xmlSAXHandlerPtr oldsax = NULL;
 
11922
    xmlNodePtr content = NULL;
 
11923
    xmlNodePtr last = NULL;
 
11924
    int size;
 
11925
    xmlParserErrors ret = XML_ERR_OK;
 
11926
 
 
11927
    if (oldctxt->depth > 40) {
 
11928
        return(XML_ERR_ENTITY_LOOP);
 
11929
    }
 
11930
 
 
11931
 
 
11932
    if (lst != NULL)
 
11933
        *lst = NULL;
 
11934
    if (string == NULL)
 
11935
        return(XML_ERR_INTERNAL_ERROR);
 
11936
 
 
11937
    size = xmlStrlen(string);
 
11938
 
 
11939
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
 
11940
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
 
11941
    if (user_data != NULL)
 
11942
        ctxt->userData = user_data;
 
11943
    else
 
11944
        ctxt->userData = ctxt;
 
11945
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
 
11946
    ctxt->dict = oldctxt->dict;
 
11947
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
11948
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
11949
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
11950
 
 
11951
    oldsax = ctxt->sax;
 
11952
    ctxt->sax = oldctxt->sax;
 
11953
    xmlDetectSAX2(ctxt);
 
11954
    ctxt->replaceEntities = oldctxt->replaceEntities;
 
11955
    ctxt->options = oldctxt->options;
 
11956
    
 
11957
    ctxt->_private = oldctxt->_private;
 
11958
    if (oldctxt->myDoc == NULL) {
 
11959
        newDoc = xmlNewDoc(BAD_CAST "1.0");
 
11960
        if (newDoc == NULL) {
 
11961
            ctxt->sax = oldsax;
 
11962
            ctxt->dict = NULL;
 
11963
            xmlFreeParserCtxt(ctxt);
 
11964
            return(XML_ERR_INTERNAL_ERROR);
 
11965
        }
 
11966
        newDoc->dict = ctxt->dict;
 
11967
        xmlDictReference(newDoc->dict);
 
11968
        ctxt->myDoc = newDoc;
 
11969
    } else {
 
11970
        ctxt->myDoc = oldctxt->myDoc;
 
11971
        content = ctxt->myDoc->children;
 
11972
        last = ctxt->myDoc->last;
 
11973
    }
 
11974
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
11975
    if (newRoot == NULL) {
 
11976
        ctxt->sax = oldsax;
 
11977
        ctxt->dict = NULL;
 
11978
        xmlFreeParserCtxt(ctxt);
 
11979
        if (newDoc != NULL) {
 
11980
            xmlFreeDoc(newDoc);
 
11981
        }
 
11982
        return(XML_ERR_INTERNAL_ERROR);
 
11983
    }
 
11984
    ctxt->myDoc->children = NULL;
 
11985
    ctxt->myDoc->last = NULL;
 
11986
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
 
11987
    nodePush(ctxt, ctxt->myDoc->children);
 
11988
    ctxt->instate = XML_PARSER_CONTENT;
 
11989
    ctxt->depth = oldctxt->depth + 1;
 
11990
 
 
11991
    ctxt->validate = 0;
 
11992
    ctxt->loadsubset = oldctxt->loadsubset;
 
11993
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
 
11994
        /*
 
11995
         * ID/IDREF registration will be done in xmlValidateElement below
 
11996
         */
 
11997
        ctxt->loadsubset |= XML_SKIP_IDS;
 
11998
    }
 
11999
    ctxt->dictNames = oldctxt->dictNames;
 
12000
    ctxt->attsDefault = oldctxt->attsDefault;
 
12001
    ctxt->attsSpecial = oldctxt->attsSpecial;
 
12002
 
 
12003
    xmlParseContent(ctxt);
 
12004
    if ((RAW == '<') && (NXT(1) == '/')) {
 
12005
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
12006
    } else if (RAW != 0) {
 
12007
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
12008
    }
 
12009
    if (ctxt->node != ctxt->myDoc->children) {
 
12010
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
12011
    }
 
12012
 
 
12013
    if (!ctxt->wellFormed) {
 
12014
        if (ctxt->errNo == 0)
 
12015
            ret = XML_ERR_INTERNAL_ERROR;
 
12016
        else
 
12017
            ret = (xmlParserErrors)ctxt->errNo;
 
12018
    } else {
 
12019
      ret = XML_ERR_OK;
 
12020
    }
 
12021
    
 
12022
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
 
12023
        xmlNodePtr cur;
 
12024
 
 
12025
        /*
 
12026
         * Return the newly created nodeset after unlinking it from
 
12027
         * they pseudo parent.
 
12028
         */
 
12029
        cur = ctxt->myDoc->children->children;
 
12030
        *lst = cur;
 
12031
        while (cur != NULL) {
 
12032
#ifdef LIBXML_VALID_ENABLED
 
12033
            if ((oldctxt->validate) && (oldctxt->wellFormed) &&
 
12034
                (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
 
12035
                (cur->type == XML_ELEMENT_NODE)) {
 
12036
                oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
 
12037
                        oldctxt->myDoc, cur);
 
12038
            }
 
12039
#endif /* LIBXML_VALID_ENABLED */
 
12040
            cur->parent = NULL;
 
12041
            cur = cur->next;
 
12042
        }
 
12043
        ctxt->myDoc->children->children = NULL;
 
12044
    }
 
12045
    if (ctxt->myDoc != NULL) {
 
12046
        xmlFreeNode(ctxt->myDoc->children);
 
12047
        ctxt->myDoc->children = content;
 
12048
        ctxt->myDoc->last = last;
 
12049
    }
 
12050
        
 
12051
    ctxt->sax = oldsax;
 
12052
    ctxt->dict = NULL;
 
12053
    ctxt->attsDefault = NULL;
 
12054
    ctxt->attsSpecial = NULL;
 
12055
    xmlFreeParserCtxt(ctxt);
 
12056
    if (newDoc != NULL) {
 
12057
        xmlFreeDoc(newDoc);
 
12058
    }
 
12059
    
 
12060
    return(ret);
 
12061
}
 
12062
 
 
12063
/**
 
12064
 * xmlParseInNodeContext:
 
12065
 * @node:  the context node
 
12066
 * @data:  the input string
 
12067
 * @datalen:  the input string length in bytes
 
12068
 * @options:  a combination of xmlParserOption
 
12069
 * @lst:  the return value for the set of parsed nodes
 
12070
 *
 
12071
 * Parse a well-balanced chunk of an XML document
 
12072
 * within the context (DTD, namespaces, etc ...) of the given node.
 
12073
 *
 
12074
 * The allowed sequence for the data is a Well Balanced Chunk defined by
 
12075
 * the content production in the XML grammar:
 
12076
 *
 
12077
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
12078
 *
 
12079
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
 
12080
 * error code otherwise
 
12081
 */
 
12082
xmlParserErrors
 
12083
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
 
12084
                      int options, xmlNodePtr *lst) {
 
12085
#ifdef SAX2
 
12086
    xmlParserCtxtPtr ctxt;
 
12087
    xmlDocPtr doc = NULL;
 
12088
    xmlNodePtr fake, cur;
 
12089
    int nsnr = 0;
 
12090
 
 
12091
    xmlParserErrors ret = XML_ERR_OK;
 
12092
 
 
12093
    /*
 
12094
     * check all input parameters, grab the document
 
12095
     */
 
12096
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
 
12097
        return(XML_ERR_INTERNAL_ERROR);
 
12098
    switch (node->type) {
 
12099
        case XML_ELEMENT_NODE:
 
12100
        case XML_ATTRIBUTE_NODE:
 
12101
        case XML_TEXT_NODE:
 
12102
        case XML_CDATA_SECTION_NODE:
 
12103
        case XML_ENTITY_REF_NODE:
 
12104
        case XML_PI_NODE:
 
12105
        case XML_COMMENT_NODE:
 
12106
        case XML_DOCUMENT_NODE:
 
12107
        case XML_HTML_DOCUMENT_NODE:
 
12108
            break;
 
12109
        default:
 
12110
            return(XML_ERR_INTERNAL_ERROR);
 
12111
 
 
12112
    }
 
12113
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
 
12114
           (node->type != XML_DOCUMENT_NODE) &&
 
12115
           (node->type != XML_HTML_DOCUMENT_NODE))
 
12116
        node = node->parent;
 
12117
    if (node == NULL)
 
12118
        return(XML_ERR_INTERNAL_ERROR);
 
12119
    if (node->type == XML_ELEMENT_NODE)
 
12120
        doc = node->doc;
 
12121
    else
 
12122
        doc = (xmlDocPtr) node;
 
12123
    if (doc == NULL)
 
12124
        return(XML_ERR_INTERNAL_ERROR);
 
12125
 
 
12126
    /*
 
12127
     * allocate a context and set-up everything not related to the
 
12128
     * node position in the tree
 
12129
     */
 
12130
    if (doc->type == XML_DOCUMENT_NODE)
 
12131
        ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
 
12132
#ifdef LIBXML_HTML_ENABLED
 
12133
    else if (doc->type == XML_HTML_DOCUMENT_NODE)
 
12134
        ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
 
12135
#endif
 
12136
    else
 
12137
        return(XML_ERR_INTERNAL_ERROR);
 
12138
 
 
12139
    if (ctxt == NULL)
 
12140
        return(XML_ERR_NO_MEMORY);
 
12141
    fake = xmlNewComment(NULL);
 
12142
    if (fake == NULL) {
 
12143
        xmlFreeParserCtxt(ctxt);
 
12144
        return(XML_ERR_NO_MEMORY);
 
12145
    }
 
12146
    xmlAddChild(node, fake);
 
12147
 
 
12148
    /* 
 
12149
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
 
12150
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
 
12151
     * we must wait until the last moment to free the original one.
 
12152
     */
 
12153
    if (doc->dict != NULL) {
 
12154
        if (ctxt->dict != NULL)
 
12155
            xmlDictFree(ctxt->dict);
 
12156
        ctxt->dict = doc->dict;
 
12157
    } else
 
12158
        options |= XML_PARSE_NODICT;
 
12159
 
 
12160
    xmlCtxtUseOptions(ctxt, options);
 
12161
    xmlDetectSAX2(ctxt);
 
12162
    ctxt->myDoc = doc;
 
12163
 
 
12164
    if (node->type == XML_ELEMENT_NODE) {
 
12165
        nodePush(ctxt, node);
 
12166
        /*
 
12167
         * initialize the SAX2 namespaces stack
 
12168
         */
 
12169
        cur = node;
 
12170
        while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
 
12171
            xmlNsPtr ns = cur->nsDef;
 
12172
            const xmlChar *iprefix, *ihref;
 
12173
 
 
12174
            while (ns != NULL) {
 
12175
                if (ctxt->dict) {
 
12176
                    iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
 
12177
                    ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
 
12178
                } else {
 
12179
                    iprefix = ns->prefix;
 
12180
                    ihref = ns->href;
 
12181
                }
 
12182
 
 
12183
                if (xmlGetNamespace(ctxt, iprefix) == NULL) {
 
12184
                    nsPush(ctxt, iprefix, ihref);
 
12185
                    nsnr++;
 
12186
                }
 
12187
                ns = ns->next;
 
12188
            }
 
12189
            cur = cur->parent;
 
12190
        }
 
12191
        ctxt->instate = XML_PARSER_CONTENT;
 
12192
    } 
 
12193
 
 
12194
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
 
12195
        /*
 
12196
         * ID/IDREF registration will be done in xmlValidateElement below
 
12197
         */
 
12198
        ctxt->loadsubset |= XML_SKIP_IDS;
 
12199
    }
 
12200
 
 
12201
#ifdef LIBXML_HTML_ENABLED
 
12202
    if (doc->type == XML_HTML_DOCUMENT_NODE)
 
12203
        __htmlParseContent(ctxt);
 
12204
    else
 
12205
#endif
 
12206
        xmlParseContent(ctxt);
 
12207
 
 
12208
    nsPop(ctxt, nsnr);
 
12209
    if ((RAW == '<') && (NXT(1) == '/')) {
 
12210
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
12211
    } else if (RAW != 0) {
 
12212
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
12213
    }
 
12214
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
 
12215
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
12216
        ctxt->wellFormed = 0;
 
12217
    }
 
12218
 
 
12219
    if (!ctxt->wellFormed) {
 
12220
        if (ctxt->errNo == 0)
 
12221
            ret = XML_ERR_INTERNAL_ERROR;
 
12222
        else
 
12223
            ret = (xmlParserErrors)ctxt->errNo;
 
12224
    } else {
 
12225
        ret = XML_ERR_OK;
 
12226
    }
 
12227
    
 
12228
    /*
 
12229
     * Return the newly created nodeset after unlinking it from
 
12230
     * the pseudo sibling.
 
12231
     */
 
12232
    
 
12233
    cur = fake->next;
 
12234
    fake->next = NULL;
 
12235
    node->last = fake;
 
12236
 
 
12237
    if (cur != NULL) {
 
12238
        cur->prev = NULL;
 
12239
    }
 
12240
 
 
12241
    *lst = cur;
 
12242
 
 
12243
    while (cur != NULL) {
 
12244
        cur->parent = NULL;
 
12245
        cur = cur->next;
 
12246
    }
 
12247
 
 
12248
    xmlUnlinkNode(fake);
 
12249
    xmlFreeNode(fake);
 
12250
 
 
12251
 
 
12252
    if (ret != XML_ERR_OK) {
 
12253
        xmlFreeNodeList(*lst);
 
12254
        *lst = NULL;
 
12255
    }
 
12256
 
 
12257
    if (doc->dict != NULL)
 
12258
        ctxt->dict = NULL;
 
12259
    xmlFreeParserCtxt(ctxt);
 
12260
    
 
12261
    return(ret);
 
12262
#else /* !SAX2 */
 
12263
    return(XML_ERR_INTERNAL_ERROR);
 
12264
#endif
 
12265
}
 
12266
 
 
12267
#ifdef LIBXML_SAX1_ENABLED
 
12268
/**
 
12269
 * xmlParseBalancedChunkMemoryRecover:
 
12270
 * @doc:  the document the chunk pertains to
 
12271
 * @sax:  the SAX handler bloc (possibly NULL)
 
12272
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
12273
 * @depth:  Used for loop detection, use 0
 
12274
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
12275
 * @lst:  the return value for the set of parsed nodes
 
12276
 * @recover: return nodes even if the data is broken (use 0)
 
12277
 *
 
12278
 *
 
12279
 * Parse a well-balanced chunk of an XML document
 
12280
 * called by the parser
 
12281
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
12282
 * the content production in the XML grammar:
 
12283
 *
 
12284
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
12285
 *
 
12286
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
 
12287
 *    the parser error code otherwise
 
12288
 *
 
12289
 * In case recover is set to 1, the nodelist will not be empty even if
 
12290
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
 
12291
 * some extent.
 
12292
 */
 
12293
int
 
12294
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
 
12295
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
 
12296
     int recover) {
 
12297
    xmlParserCtxtPtr ctxt;
 
12298
    xmlDocPtr newDoc;
 
12299
    xmlSAXHandlerPtr oldsax = NULL;
 
12300
    xmlNodePtr content, newRoot;
 
12301
    int size;
 
12302
    int ret = 0;
 
12303
 
 
12304
    if (depth > 40) {
 
12305
        return(XML_ERR_ENTITY_LOOP);
 
12306
    }
 
12307
 
 
12308
 
 
12309
    if (lst != NULL)
 
12310
        *lst = NULL;
 
12311
    if (string == NULL)
 
12312
        return(-1);
 
12313
 
 
12314
    size = xmlStrlen(string);
 
12315
 
 
12316
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
 
12317
    if (ctxt == NULL) return(-1);
 
12318
    ctxt->userData = ctxt;
 
12319
    if (sax != NULL) {
 
12320
        oldsax = ctxt->sax;
 
12321
        ctxt->sax = sax;
 
12322
        if (user_data != NULL)
 
12323
            ctxt->userData = user_data;
 
12324
    }
 
12325
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
12326
    if (newDoc == NULL) {
 
12327
        xmlFreeParserCtxt(ctxt);
 
12328
        return(-1);
 
12329
    }
 
12330
    if ((doc != NULL) && (doc->dict != NULL)) {
 
12331
        xmlDictFree(ctxt->dict);
 
12332
        ctxt->dict = doc->dict;
 
12333
        xmlDictReference(ctxt->dict);
 
12334
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
12335
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
12336
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
12337
        ctxt->dictNames = 1;
 
12338
    } else {
 
12339
        xmlCtxtUseOptions(ctxt, XML_PARSE_NODICT);
 
12340
    }
 
12341
    if (doc != NULL) {
 
12342
        newDoc->intSubset = doc->intSubset;
 
12343
        newDoc->extSubset = doc->extSubset;
 
12344
    }
 
12345
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
12346
    if (newRoot == NULL) {
 
12347
        if (sax != NULL)
 
12348
            ctxt->sax = oldsax;
 
12349
        xmlFreeParserCtxt(ctxt);
 
12350
        newDoc->intSubset = NULL;
 
12351
        newDoc->extSubset = NULL;
 
12352
        xmlFreeDoc(newDoc);
 
12353
        return(-1);
 
12354
    }
 
12355
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
12356
    nodePush(ctxt, newRoot);
 
12357
    if (doc == NULL) {
 
12358
        ctxt->myDoc = newDoc;
 
12359
    } else {
 
12360
        ctxt->myDoc = newDoc;
 
12361
        newDoc->children->doc = doc;
 
12362
        /* Ensure that doc has XML spec namespace */
 
12363
        xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
 
12364
        newDoc->oldNs = doc->oldNs;
 
12365
    }
 
12366
    ctxt->instate = XML_PARSER_CONTENT;
 
12367
    ctxt->depth = depth;
 
12368
 
 
12369
    /*
 
12370
     * Doing validity checking on chunk doesn't make sense
 
12371
     */
 
12372
    ctxt->validate = 0;
 
12373
    ctxt->loadsubset = 0;
 
12374
    xmlDetectSAX2(ctxt);
 
12375
 
 
12376
    if ( doc != NULL ){
 
12377
        content = doc->children;
 
12378
        doc->children = NULL;
 
12379
        xmlParseContent(ctxt);
 
12380
        doc->children = content;
 
12381
    }
 
12382
    else {
 
12383
        xmlParseContent(ctxt);
 
12384
    }
 
12385
    if ((RAW == '<') && (NXT(1) == '/')) {
 
12386
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
12387
    } else if (RAW != 0) {
 
12388
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
12389
    }
 
12390
    if (ctxt->node != newDoc->children) {
 
12391
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
12392
    }
 
12393
 
 
12394
    if (!ctxt->wellFormed) {
 
12395
        if (ctxt->errNo == 0)
 
12396
            ret = 1;
 
12397
        else
 
12398
            ret = ctxt->errNo;
 
12399
    } else {
 
12400
      ret = 0;
 
12401
    }
 
12402
    
 
12403
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
 
12404
        xmlNodePtr cur;
 
12405
 
 
12406
        /*
 
12407
         * Return the newly created nodeset after unlinking it from
 
12408
         * they pseudo parent.
 
12409
         */
 
12410
        cur = newDoc->children->children;
 
12411
        *lst = cur;
 
12412
        while (cur != NULL) {
 
12413
            xmlSetTreeDoc(cur, doc);
 
12414
            cur->parent = NULL;
 
12415
            cur = cur->next;
 
12416
        }
 
12417
        newDoc->children->children = NULL;
 
12418
    }
 
12419
        
 
12420
    if (sax != NULL) 
 
12421
        ctxt->sax = oldsax;
 
12422
    xmlFreeParserCtxt(ctxt);
 
12423
    newDoc->intSubset = NULL;
 
12424
    newDoc->extSubset = NULL;
 
12425
    newDoc->oldNs = NULL;
 
12426
    xmlFreeDoc(newDoc);
 
12427
    
 
12428
    return(ret);
 
12429
}
 
12430
 
 
12431
/**
 
12432
 * xmlSAXParseEntity:
 
12433
 * @sax:  the SAX handler block
 
12434
 * @filename:  the filename
 
12435
 *
 
12436
 * parse an XML external entity out of context and build a tree.
 
12437
 * It use the given SAX function block to handle the parsing callback.
 
12438
 * If sax is NULL, fallback to the default DOM tree building routines.
 
12439
 *
 
12440
 * [78] extParsedEnt ::= TextDecl? content
 
12441
 *
 
12442
 * This correspond to a "Well Balanced" chunk
 
12443
 *
 
12444
 * Returns the resulting document tree
 
12445
 */
 
12446
 
 
12447
xmlDocPtr
 
12448
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
 
12449
    xmlDocPtr ret;
 
12450
    xmlParserCtxtPtr ctxt;
 
12451
 
 
12452
    ctxt = xmlCreateFileParserCtxt(filename);
 
12453
    if (ctxt == NULL) {
 
12454
        return(NULL);
 
12455
    }
 
12456
    if (sax != NULL) {
 
12457
        if (ctxt->sax != NULL)
 
12458
            xmlFree(ctxt->sax);
 
12459
        ctxt->sax = sax;
 
12460
        ctxt->userData = NULL;
 
12461
    }
 
12462
 
 
12463
    xmlParseExtParsedEnt(ctxt);
 
12464
 
 
12465
    if (ctxt->wellFormed)
 
12466
        ret = ctxt->myDoc;
 
12467
    else {
 
12468
        ret = NULL;
 
12469
        xmlFreeDoc(ctxt->myDoc);
 
12470
        ctxt->myDoc = NULL;
 
12471
    }
 
12472
    if (sax != NULL)
 
12473
        ctxt->sax = NULL;
 
12474
    xmlFreeParserCtxt(ctxt);
 
12475
    
 
12476
    return(ret);
 
12477
}
 
12478
 
 
12479
/**
 
12480
 * xmlParseEntity:
 
12481
 * @filename:  the filename
 
12482
 *
 
12483
 * parse an XML external entity out of context and build a tree.
 
12484
 *
 
12485
 * [78] extParsedEnt ::= TextDecl? content
 
12486
 *
 
12487
 * This correspond to a "Well Balanced" chunk
 
12488
 *
 
12489
 * Returns the resulting document tree
 
12490
 */
 
12491
 
 
12492
xmlDocPtr
 
12493
xmlParseEntity(const char *filename) {
 
12494
    return(xmlSAXParseEntity(NULL, filename));
 
12495
}
 
12496
#endif /* LIBXML_SAX1_ENABLED */
 
12497
 
 
12498
/**
 
12499
 * xmlCreateEntityParserCtxt:
 
12500
 * @URL:  the entity URL
 
12501
 * @ID:  the entity PUBLIC ID
 
12502
 * @base:  a possible base for the target URI
 
12503
 *
 
12504
 * Create a parser context for an external entity
 
12505
 * Automatic support for ZLIB/Compress compressed document is provided
 
12506
 * by default if found at compile-time.
 
12507
 *
 
12508
 * Returns the new parser context or NULL
 
12509
 */
 
12510
xmlParserCtxtPtr
 
12511
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
 
12512
                          const xmlChar *base) {
 
12513
    xmlParserCtxtPtr ctxt;
 
12514
    xmlParserInputPtr inputStream;
 
12515
    char *directory = NULL;
 
12516
    xmlChar *uri;
 
12517
    
 
12518
    ctxt = xmlNewParserCtxt();
 
12519
    if (ctxt == NULL) {
 
12520
        return(NULL);
 
12521
    }
 
12522
 
 
12523
    uri = xmlBuildURI(URL, base);
 
12524
 
 
12525
    if (uri == NULL) {
 
12526
        inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
 
12527
        if (inputStream == NULL) {
 
12528
            xmlFreeParserCtxt(ctxt);
 
12529
            return(NULL);
 
12530
        }
 
12531
 
 
12532
        inputPush(ctxt, inputStream);
 
12533
 
 
12534
        if ((ctxt->directory == NULL) && (directory == NULL))
 
12535
            directory = xmlParserGetDirectory((char *)URL);
 
12536
        if ((ctxt->directory == NULL) && (directory != NULL))
 
12537
            ctxt->directory = directory;
 
12538
    } else {
 
12539
        inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
 
12540
        if (inputStream == NULL) {
 
12541
            xmlFree(uri);
 
12542
            xmlFreeParserCtxt(ctxt);
 
12543
            return(NULL);
 
12544
        }
 
12545
 
 
12546
        inputPush(ctxt, inputStream);
 
12547
 
 
12548
        if ((ctxt->directory == NULL) && (directory == NULL))
 
12549
            directory = xmlParserGetDirectory((char *)uri);
 
12550
        if ((ctxt->directory == NULL) && (directory != NULL))
 
12551
            ctxt->directory = directory;
 
12552
        xmlFree(uri);
 
12553
    }
 
12554
    return(ctxt);
 
12555
}
 
12556
 
 
12557
/************************************************************************
 
12558
 *                                                                      *
 
12559
 *              Front ends when parsing from a file                     *
 
12560
 *                                                                      *
 
12561
 ************************************************************************/
 
12562
 
 
12563
/**
 
12564
 * xmlCreateURLParserCtxt:
 
12565
 * @filename:  the filename or URL
 
12566
 * @options:  a combination of xmlParserOption
 
12567
 *
 
12568
 * Create a parser context for a file or URL content. 
 
12569
 * Automatic support for ZLIB/Compress compressed document is provided
 
12570
 * by default if found at compile-time and for file accesses
 
12571
 *
 
12572
 * Returns the new parser context or NULL
 
12573
 */
 
12574
xmlParserCtxtPtr
 
12575
xmlCreateURLParserCtxt(const char *filename, int options)
 
12576
{
 
12577
    xmlParserCtxtPtr ctxt;
 
12578
    xmlParserInputPtr inputStream;
 
12579
    char *directory = NULL;
 
12580
 
 
12581
    ctxt = xmlNewParserCtxt();
 
12582
    if (ctxt == NULL) {
 
12583
        xmlErrMemory(NULL, "cannot allocate parser context");
 
12584
        return(NULL);
 
12585
    }
 
12586
 
 
12587
    if (options)
 
12588
        xmlCtxtUseOptions(ctxt, options);
 
12589
    ctxt->linenumbers = 1;
 
12590
    
 
12591
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
 
12592
    if (inputStream == NULL) {
 
12593
        xmlFreeParserCtxt(ctxt);
 
12594
        return(NULL);
 
12595
    }
 
12596
 
 
12597
    inputPush(ctxt, inputStream);
 
12598
    if ((ctxt->directory == NULL) && (directory == NULL))
 
12599
        directory = xmlParserGetDirectory(filename);
 
12600
    if ((ctxt->directory == NULL) && (directory != NULL))
 
12601
        ctxt->directory = directory;
 
12602
 
 
12603
    return(ctxt);
 
12604
}
 
12605
 
 
12606
/**
 
12607
 * xmlCreateFileParserCtxt:
 
12608
 * @filename:  the filename
 
12609
 *
 
12610
 * Create a parser context for a file content. 
 
12611
 * Automatic support for ZLIB/Compress compressed document is provided
 
12612
 * by default if found at compile-time.
 
12613
 *
 
12614
 * Returns the new parser context or NULL
 
12615
 */
 
12616
xmlParserCtxtPtr
 
12617
xmlCreateFileParserCtxt(const char *filename)
 
12618
{
 
12619
    return(xmlCreateURLParserCtxt(filename, 0));
 
12620
}
 
12621
 
 
12622
#ifdef LIBXML_SAX1_ENABLED
 
12623
/**
 
12624
 * xmlSAXParseFileWithData:
 
12625
 * @sax:  the SAX handler block
 
12626
 * @filename:  the filename
 
12627
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
12628
 *             documents
 
12629
 * @data:  the userdata
 
12630
 *
 
12631
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
12632
 * compressed document is provided by default if found at compile-time.
 
12633
 * It use the given SAX function block to handle the parsing callback.
 
12634
 * If sax is NULL, fallback to the default DOM tree building routines.
 
12635
 *
 
12636
 * User data (void *) is stored within the parser context in the
 
12637
 * context's _private member, so it is available nearly everywhere in libxml
 
12638
 *
 
12639
 * Returns the resulting document tree
 
12640
 */
 
12641
 
 
12642
xmlDocPtr
 
12643
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
 
12644
                        int recovery, void *data) {
 
12645
    xmlDocPtr ret;
 
12646
    xmlParserCtxtPtr ctxt;
 
12647
 
 
12648
    xmlInitParser();
 
12649
 
 
12650
    ctxt = xmlCreateFileParserCtxt(filename);
 
12651
    if (ctxt == NULL) {
 
12652
        return(NULL);
 
12653
    }
 
12654
    if (sax != NULL) {
 
12655
        if (ctxt->sax != NULL)
 
12656
            xmlFree(ctxt->sax);
 
12657
        ctxt->sax = sax;
 
12658
    }
 
12659
    xmlDetectSAX2(ctxt);
 
12660
    if (data!=NULL) {
 
12661
        ctxt->_private = data;
 
12662
    }
 
12663
 
 
12664
    if (ctxt->directory == NULL)
 
12665
        ctxt->directory = xmlParserGetDirectory(filename);
 
12666
 
 
12667
    ctxt->recovery = recovery;
 
12668
 
 
12669
    xmlParseDocument(ctxt);
 
12670
 
 
12671
    if ((ctxt->wellFormed) || recovery) {
 
12672
        ret = ctxt->myDoc;
 
12673
        if (ret != NULL) {
 
12674
            if (ctxt->input->buf->compressed > 0)
 
12675
                ret->compression = 9;
 
12676
            else
 
12677
                ret->compression = ctxt->input->buf->compressed;
 
12678
        }
 
12679
    }
 
12680
    else {
 
12681
       ret = NULL;
 
12682
       xmlFreeDoc(ctxt->myDoc);
 
12683
       ctxt->myDoc = NULL;
 
12684
    }
 
12685
    if (sax != NULL)
 
12686
        ctxt->sax = NULL;
 
12687
    xmlFreeParserCtxt(ctxt);
 
12688
    
 
12689
    return(ret);
 
12690
}
 
12691
 
 
12692
/**
 
12693
 * xmlSAXParseFile:
 
12694
 * @sax:  the SAX handler block
 
12695
 * @filename:  the filename
 
12696
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
12697
 *             documents
 
12698
 *
 
12699
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
12700
 * compressed document is provided by default if found at compile-time.
 
12701
 * It use the given SAX function block to handle the parsing callback.
 
12702
 * If sax is NULL, fallback to the default DOM tree building routines.
 
12703
 *
 
12704
 * Returns the resulting document tree
 
12705
 */
 
12706
 
 
12707
xmlDocPtr
 
12708
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
 
12709
                          int recovery) {
 
12710
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
 
12711
}
 
12712
 
 
12713
/**
 
12714
 * xmlRecoverDoc:
 
12715
 * @cur:  a pointer to an array of xmlChar
 
12716
 *
 
12717
 * parse an XML in-memory document and build a tree.
 
12718
 * In the case the document is not Well Formed, a attempt to build a
 
12719
 * tree is tried anyway
 
12720
 *
 
12721
 * Returns the resulting document tree or NULL in case of failure
 
12722
 */
 
12723
 
 
12724
xmlDocPtr
 
12725
xmlRecoverDoc(xmlChar *cur) {
 
12726
    return(xmlSAXParseDoc(NULL, cur, 1));
 
12727
}
 
12728
 
 
12729
/**
 
12730
 * xmlParseFile:
 
12731
 * @filename:  the filename
 
12732
 *
 
12733
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
12734
 * compressed document is provided by default if found at compile-time.
 
12735
 *
 
12736
 * Returns the resulting document tree if the file was wellformed,
 
12737
 * NULL otherwise.
 
12738
 */
 
12739
 
 
12740
xmlDocPtr
 
12741
xmlParseFile(const char *filename) {
 
12742
    return(xmlSAXParseFile(NULL, filename, 0));
 
12743
}
 
12744
 
 
12745
/**
 
12746
 * xmlRecoverFile:
 
12747
 * @filename:  the filename
 
12748
 *
 
12749
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
12750
 * compressed document is provided by default if found at compile-time.
 
12751
 * In the case the document is not Well Formed, it attempts to build
 
12752
 * a tree anyway
 
12753
 *
 
12754
 * Returns the resulting document tree or NULL in case of failure
 
12755
 */
 
12756
 
 
12757
xmlDocPtr
 
12758
xmlRecoverFile(const char *filename) {
 
12759
    return(xmlSAXParseFile(NULL, filename, 1));
 
12760
}
 
12761
 
 
12762
 
 
12763
/**
 
12764
 * xmlSetupParserForBuffer:
 
12765
 * @ctxt:  an XML parser context
 
12766
 * @buffer:  a xmlChar * buffer
 
12767
 * @filename:  a file name
 
12768
 *
 
12769
 * Setup the parser context to parse a new buffer; Clears any prior
 
12770
 * contents from the parser context. The buffer parameter must not be
 
12771
 * NULL, but the filename parameter can be
 
12772
 */
 
12773
void
 
12774
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
 
12775
                             const char* filename)
 
12776
{
 
12777
    xmlParserInputPtr input;
 
12778
 
 
12779
    if ((ctxt == NULL) || (buffer == NULL))
 
12780
        return;
 
12781
 
 
12782
    input = xmlNewInputStream(ctxt);
 
12783
    if (input == NULL) {
 
12784
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
 
12785
        xmlClearParserCtxt(ctxt);
 
12786
        return;
 
12787
    }
 
12788
  
 
12789
    xmlClearParserCtxt(ctxt);
 
12790
    if (filename != NULL)
 
12791
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
 
12792
    input->base = buffer;
 
12793
    input->cur = buffer;
 
12794
    input->end = &buffer[xmlStrlen(buffer)];
 
12795
    inputPush(ctxt, input);
 
12796
}
 
12797
 
 
12798
/**
 
12799
 * xmlSAXUserParseFile:
 
12800
 * @sax:  a SAX handler
 
12801
 * @user_data:  The user data returned on SAX callbacks
 
12802
 * @filename:  a file name
 
12803
 *
 
12804
 * parse an XML file and call the given SAX handler routines.
 
12805
 * Automatic support for ZLIB/Compress compressed document is provided
 
12806
 * 
 
12807
 * Returns 0 in case of success or a error number otherwise
 
12808
 */
 
12809
int
 
12810
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
 
12811
                    const char *filename) {
 
12812
    int ret = 0;
 
12813
    xmlParserCtxtPtr ctxt;
 
12814
    
 
12815
    ctxt = xmlCreateFileParserCtxt(filename);
 
12816
    if (ctxt == NULL) return -1;
 
12817
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
12818
        xmlFree(ctxt->sax);
 
12819
    ctxt->sax = sax;
 
12820
    xmlDetectSAX2(ctxt);
 
12821
 
 
12822
    if (user_data != NULL)
 
12823
        ctxt->userData = user_data;
 
12824
    
 
12825
    xmlParseDocument(ctxt);
 
12826
    
 
12827
    if (ctxt->wellFormed)
 
12828
        ret = 0;
 
12829
    else {
 
12830
        if (ctxt->errNo != 0)
 
12831
            ret = ctxt->errNo;
 
12832
        else
 
12833
            ret = -1;
 
12834
    }
 
12835
    if (sax != NULL)
 
12836
        ctxt->sax = NULL;
 
12837
    if (ctxt->myDoc != NULL) {
 
12838
        xmlFreeDoc(ctxt->myDoc);
 
12839
        ctxt->myDoc = NULL;
 
12840
    }
 
12841
    xmlFreeParserCtxt(ctxt);
 
12842
    
 
12843
    return ret;
 
12844
}
 
12845
#endif /* LIBXML_SAX1_ENABLED */
 
12846
 
 
12847
/************************************************************************
 
12848
 *                                                                      *
 
12849
 *              Front ends when parsing from memory                     *
 
12850
 *                                                                      *
 
12851
 ************************************************************************/
 
12852
 
 
12853
/**
 
12854
 * xmlCreateMemoryParserCtxt:
 
12855
 * @buffer:  a pointer to a char array
 
12856
 * @size:  the size of the array
 
12857
 *
 
12858
 * Create a parser context for an XML in-memory document.
 
12859
 *
 
12860
 * Returns the new parser context or NULL
 
12861
 */
 
12862
xmlParserCtxtPtr
 
12863
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
 
12864
    xmlParserCtxtPtr ctxt;
 
12865
    xmlParserInputPtr input;
 
12866
    xmlParserInputBufferPtr buf;
 
12867
 
 
12868
    if (buffer == NULL)
 
12869
        return(NULL);
 
12870
    if (size <= 0)
 
12871
        return(NULL);
 
12872
 
 
12873
    ctxt = xmlNewParserCtxt();
 
12874
    if (ctxt == NULL)
 
12875
        return(NULL);
 
12876
 
 
12877
    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
 
12878
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 
12879
    if (buf == NULL) {
 
12880
        xmlFreeParserCtxt(ctxt);
 
12881
        return(NULL);
 
12882
    }
 
12883
 
 
12884
    input = xmlNewInputStream(ctxt);
 
12885
    if (input == NULL) {
 
12886
        xmlFreeParserInputBuffer(buf);
 
12887
        xmlFreeParserCtxt(ctxt);
 
12888
        return(NULL);
 
12889
    }
 
12890
 
 
12891
    input->filename = NULL;
 
12892
    input->buf = buf;
 
12893
    input->base = input->buf->buffer->content;
 
12894
    input->cur = input->buf->buffer->content;
 
12895
    input->end = &input->buf->buffer->content[input->buf->buffer->use];
 
12896
 
 
12897
    inputPush(ctxt, input);
 
12898
    return(ctxt);
 
12899
}
 
12900
 
 
12901
#ifdef LIBXML_SAX1_ENABLED
 
12902
/**
 
12903
 * xmlSAXParseMemoryWithData:
 
12904
 * @sax:  the SAX handler block
 
12905
 * @buffer:  an pointer to a char array
 
12906
 * @size:  the size of the array
 
12907
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
12908
 *             documents
 
12909
 * @data:  the userdata
 
12910
 *
 
12911
 * parse an XML in-memory block and use the given SAX function block
 
12912
 * to handle the parsing callback. If sax is NULL, fallback to the default
 
12913
 * DOM tree building routines.
 
12914
 *
 
12915
 * User data (void *) is stored within the parser context in the
 
12916
 * context's _private member, so it is available nearly everywhere in libxml
 
12917
 *
 
12918
 * Returns the resulting document tree
 
12919
 */
 
12920
 
 
12921
xmlDocPtr
 
12922
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
 
12923
                  int size, int recovery, void *data) {
 
12924
    xmlDocPtr ret;
 
12925
    xmlParserCtxtPtr ctxt;
 
12926
 
 
12927
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
12928
    if (ctxt == NULL) return(NULL);
 
12929
    if (sax != NULL) {
 
12930
        if (ctxt->sax != NULL)
 
12931
            xmlFree(ctxt->sax);
 
12932
        ctxt->sax = sax;
 
12933
    }
 
12934
    xmlDetectSAX2(ctxt);
 
12935
    if (data!=NULL) {
 
12936
        ctxt->_private=data;
 
12937
    }
 
12938
 
 
12939
    ctxt->recovery = recovery;
 
12940
 
 
12941
    xmlParseDocument(ctxt);
 
12942
 
 
12943
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
 
12944
    else {
 
12945
       ret = NULL;
 
12946
       xmlFreeDoc(ctxt->myDoc);
 
12947
       ctxt->myDoc = NULL;
 
12948
    }
 
12949
    if (sax != NULL) 
 
12950
        ctxt->sax = NULL;
 
12951
    xmlFreeParserCtxt(ctxt);
 
12952
    
 
12953
    return(ret);
 
12954
}
 
12955
 
 
12956
/**
 
12957
 * xmlSAXParseMemory:
 
12958
 * @sax:  the SAX handler block
 
12959
 * @buffer:  an pointer to a char array
 
12960
 * @size:  the size of the array
 
12961
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
 
12962
 *             documents
 
12963
 *
 
12964
 * parse an XML in-memory block and use the given SAX function block
 
12965
 * to handle the parsing callback. If sax is NULL, fallback to the default
 
12966
 * DOM tree building routines.
 
12967
 * 
 
12968
 * Returns the resulting document tree
 
12969
 */
 
12970
xmlDocPtr
 
12971
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
 
12972
                  int size, int recovery) {
 
12973
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
 
12974
}
 
12975
 
 
12976
/**
 
12977
 * xmlParseMemory:
 
12978
 * @buffer:  an pointer to a char array
 
12979
 * @size:  the size of the array
 
12980
 *
 
12981
 * parse an XML in-memory block and build a tree.
 
12982
 * 
 
12983
 * Returns the resulting document tree
 
12984
 */
 
12985
 
 
12986
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
 
12987
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
 
12988
}
 
12989
 
 
12990
/**
 
12991
 * xmlRecoverMemory:
 
12992
 * @buffer:  an pointer to a char array
 
12993
 * @size:  the size of the array
 
12994
 *
 
12995
 * parse an XML in-memory block and build a tree.
 
12996
 * In the case the document is not Well Formed, an attempt to
 
12997
 * build a tree is tried anyway
 
12998
 *
 
12999
 * Returns the resulting document tree or NULL in case of error
 
13000
 */
 
13001
 
 
13002
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
 
13003
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
 
13004
}
 
13005
 
 
13006
/**
 
13007
 * xmlSAXUserParseMemory:
 
13008
 * @sax:  a SAX handler
 
13009
 * @user_data:  The user data returned on SAX callbacks
 
13010
 * @buffer:  an in-memory XML document input
 
13011
 * @size:  the length of the XML document in bytes
 
13012
 *
 
13013
 * A better SAX parsing routine.
 
13014
 * parse an XML in-memory buffer and call the given SAX handler routines.
 
13015
 * 
 
13016
 * Returns 0 in case of success or a error number otherwise
 
13017
 */
 
13018
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
 
13019
                          const char *buffer, int size) {
 
13020
    int ret = 0;
 
13021
    xmlParserCtxtPtr ctxt;
 
13022
    
 
13023
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
13024
    if (ctxt == NULL) return -1;
 
13025
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
13026
        xmlFree(ctxt->sax);
 
13027
    ctxt->sax = sax;
 
13028
    xmlDetectSAX2(ctxt);
 
13029
 
 
13030
    if (user_data != NULL)
 
13031
        ctxt->userData = user_data;
 
13032
    
 
13033
    xmlParseDocument(ctxt);
 
13034
    
 
13035
    if (ctxt->wellFormed)
 
13036
        ret = 0;
 
13037
    else {
 
13038
        if (ctxt->errNo != 0)
 
13039
            ret = ctxt->errNo;
 
13040
        else
 
13041
            ret = -1;
 
13042
    }
 
13043
    if (sax != NULL)
 
13044
        ctxt->sax = NULL;
 
13045
    if (ctxt->myDoc != NULL) {
 
13046
        xmlFreeDoc(ctxt->myDoc);
 
13047
        ctxt->myDoc = NULL;
 
13048
    }
 
13049
    xmlFreeParserCtxt(ctxt);
 
13050
    
 
13051
    return ret;
 
13052
}
 
13053
#endif /* LIBXML_SAX1_ENABLED */
 
13054
 
 
13055
/**
 
13056
 * xmlCreateDocParserCtxt:
 
13057
 * @cur:  a pointer to an array of xmlChar
 
13058
 *
 
13059
 * Creates a parser context for an XML in-memory document.
 
13060
 *
 
13061
 * Returns the new parser context or NULL
 
13062
 */
 
13063
xmlParserCtxtPtr
 
13064
xmlCreateDocParserCtxt(const xmlChar *cur) {
 
13065
    int len;
 
13066
 
 
13067
    if (cur == NULL)
 
13068
        return(NULL);
 
13069
    len = xmlStrlen(cur);
 
13070
    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
 
13071
}
 
13072
 
 
13073
#ifdef LIBXML_SAX1_ENABLED
 
13074
/**
 
13075
 * xmlSAXParseDoc:
 
13076
 * @sax:  the SAX handler block
 
13077
 * @cur:  a pointer to an array of xmlChar
 
13078
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
13079
 *             documents
 
13080
 *
 
13081
 * parse an XML in-memory document and build a tree.
 
13082
 * It use the given SAX function block to handle the parsing callback.
 
13083
 * If sax is NULL, fallback to the default DOM tree building routines.
 
13084
 * 
 
13085
 * Returns the resulting document tree
 
13086
 */
 
13087
 
 
13088
xmlDocPtr
 
13089
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
 
13090
    xmlDocPtr ret;
 
13091
    xmlParserCtxtPtr ctxt;
 
13092
    xmlSAXHandlerPtr oldsax = NULL;
 
13093
 
 
13094
    if (cur == NULL) return(NULL);
 
13095
 
 
13096
 
 
13097
    ctxt = xmlCreateDocParserCtxt(cur);
 
13098
    if (ctxt == NULL) return(NULL);
 
13099
    if (sax != NULL) { 
 
13100
        oldsax = ctxt->sax;
 
13101
        ctxt->sax = sax;
 
13102
        ctxt->userData = NULL;
 
13103
    }
 
13104
    xmlDetectSAX2(ctxt);
 
13105
 
 
13106
    xmlParseDocument(ctxt);
 
13107
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
 
13108
    else {
 
13109
       ret = NULL;
 
13110
       xmlFreeDoc(ctxt->myDoc);
 
13111
       ctxt->myDoc = NULL;
 
13112
    }
 
13113
    if (sax != NULL)
 
13114
        ctxt->sax = oldsax;
 
13115
    xmlFreeParserCtxt(ctxt);
 
13116
    
 
13117
    return(ret);
 
13118
}
 
13119
 
 
13120
/**
 
13121
 * xmlParseDoc:
 
13122
 * @cur:  a pointer to an array of xmlChar
 
13123
 *
 
13124
 * parse an XML in-memory document and build a tree.
 
13125
 * 
 
13126
 * Returns the resulting document tree
 
13127
 */
 
13128
 
 
13129
xmlDocPtr
 
13130
xmlParseDoc(const xmlChar *cur) {
 
13131
    return(xmlSAXParseDoc(NULL, cur, 0));
 
13132
}
 
13133
#endif /* LIBXML_SAX1_ENABLED */
 
13134
 
 
13135
#ifdef LIBXML_LEGACY_ENABLED
 
13136
/************************************************************************
 
13137
 *                                                                      *
 
13138
 *      Specific function to keep track of entities references          *
 
13139
 *      and used by the XSLT debugger                                   *
 
13140
 *                                                                      *
 
13141
 ************************************************************************/
 
13142
 
 
13143
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
 
13144
 
 
13145
/**
 
13146
 * xmlAddEntityReference:
 
13147
 * @ent : A valid entity
 
13148
 * @firstNode : A valid first node for children of entity
 
13149
 * @lastNode : A valid last node of children entity 
 
13150
 *
 
13151
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
 
13152
 */
 
13153
static void
 
13154
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
 
13155
                      xmlNodePtr lastNode)
 
13156
{
 
13157
    if (xmlEntityRefFunc != NULL) {
 
13158
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
 
13159
    }
 
13160
}
 
13161
 
 
13162
 
 
13163
/**
 
13164
 * xmlSetEntityReferenceFunc:
 
13165
 * @func: A valid function
 
13166
 *
 
13167
 * Set the function to call call back when a xml reference has been made
 
13168
 */
 
13169
void
 
13170
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
 
13171
{
 
13172
    xmlEntityRefFunc = func;
 
13173
}
 
13174
#endif /* LIBXML_LEGACY_ENABLED */
 
13175
 
 
13176
/************************************************************************
 
13177
 *                                                                      *
 
13178
 *                              Miscellaneous                           *
 
13179
 *                                                                      *
 
13180
 ************************************************************************/
 
13181
 
 
13182
#ifdef LIBXML_XPATH_ENABLED
 
13183
#include <libxml/xpath.h>
 
13184
#endif
 
13185
 
 
13186
extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
 
13187
static int xmlParserInitialized = 0;
 
13188
 
 
13189
/**
 
13190
 * xmlInitParser:
 
13191
 *
 
13192
 * Initialization function for the XML parser.
 
13193
 * This is not reentrant. Call once before processing in case of
 
13194
 * use in multithreaded programs.
 
13195
 */
 
13196
 
 
13197
void
 
13198
xmlInitParser(void) {
 
13199
    if (xmlParserInitialized != 0)
 
13200
        return;
 
13201
 
 
13202
#ifdef LIBXML_THREAD_ENABLED
 
13203
    __xmlGlobalInitMutexLock();
 
13204
    if (xmlParserInitialized == 0) {
 
13205
#endif
 
13206
        if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
 
13207
            (xmlGenericError == NULL))
 
13208
            initGenericErrorDefaultFunc(NULL);
 
13209
        xmlInitGlobals();
 
13210
        xmlInitThreads();
 
13211
        xmlInitMemory();
 
13212
        xmlInitCharEncodingHandlers();
 
13213
        xmlDefaultSAXHandlerInit();
 
13214
        xmlRegisterDefaultInputCallbacks();
 
13215
#ifdef LIBXML_OUTPUT_ENABLED
 
13216
        xmlRegisterDefaultOutputCallbacks();
 
13217
#endif /* LIBXML_OUTPUT_ENABLED */
 
13218
#ifdef LIBXML_HTML_ENABLED
 
13219
        htmlInitAutoClose();
 
13220
        htmlDefaultSAXHandlerInit();
 
13221
#endif
 
13222
#ifdef LIBXML_XPATH_ENABLED
 
13223
        xmlXPathInit();
 
13224
#endif
 
13225
        xmlParserInitialized = 1;
 
13226
#ifdef LIBXML_THREAD_ENABLED
 
13227
    }
 
13228
    __xmlGlobalInitMutexUnlock();
 
13229
#endif
 
13230
}
 
13231
 
 
13232
/**
 
13233
 * xmlCleanupParser:
 
13234
 *
 
13235
 * This function name is somewhat misleading. It does not clean up
 
13236
 * parser state, it cleans up memory allocated by the library itself.
 
13237
 * It is a cleanup function for the XML library. It tries to reclaim all
 
13238
 * related global memory allocated for the library processing.
 
13239
 * It doesn't deallocate any document related memory. One should
 
13240
 * call xmlCleanupParser() only when the process has finished using
 
13241
 * the library and all XML/HTML documents built with it.
 
13242
 * See also xmlInitParser() which has the opposite function of preparing
 
13243
 * the library for operations.
 
13244
 */
 
13245
 
 
13246
void
 
13247
xmlCleanupParser(void) {
 
13248
    if (!xmlParserInitialized)
 
13249
        return;
 
13250
 
 
13251
    xmlCleanupCharEncodingHandlers();
 
13252
#ifdef LIBXML_CATALOG_ENABLED
 
13253
    xmlCatalogCleanup();
 
13254
#endif
 
13255
    xmlDictCleanup();
 
13256
    xmlCleanupInputCallbacks();
 
13257
#ifdef LIBXML_OUTPUT_ENABLED
 
13258
    xmlCleanupOutputCallbacks();
 
13259
#endif
 
13260
#ifdef LIBXML_SCHEMAS_ENABLED
 
13261
    xmlSchemaCleanupTypes();
 
13262
    xmlRelaxNGCleanupTypes();
 
13263
#endif
 
13264
    xmlCleanupGlobals();
 
13265
    xmlResetLastError();
 
13266
    xmlCleanupThreads(); /* must be last if called not from the main thread */
 
13267
    xmlCleanupMemory();
 
13268
    xmlParserInitialized = 0;
 
13269
}
 
13270
 
 
13271
/************************************************************************
 
13272
 *                                                                      *
 
13273
 *      New set (2.6.0) of simpler and more flexible APIs               *
 
13274
 *                                                                      *
 
13275
 ************************************************************************/
 
13276
 
 
13277
/**
 
13278
 * DICT_FREE:
 
13279
 * @str:  a string
 
13280
 *
 
13281
 * Free a string if it is not owned by the "dict" dictionnary in the
 
13282
 * current scope
 
13283
 */
 
13284
#define DICT_FREE(str)                                          \
 
13285
        if ((str) && ((!dict) ||                                \
 
13286
            (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
 
13287
            xmlFree((char *)(str));
 
13288
 
 
13289
/**
 
13290
 * xmlCtxtReset:
 
13291
 * @ctxt: an XML parser context
 
13292
 *
 
13293
 * Reset a parser context
 
13294
 */
 
13295
void
 
13296
xmlCtxtReset(xmlParserCtxtPtr ctxt)
 
13297
{
 
13298
    xmlParserInputPtr input;
 
13299
    xmlDictPtr dict;
 
13300
    
 
13301
    if (ctxt == NULL)
 
13302
        return;
 
13303
 
 
13304
    dict = ctxt->dict;
 
13305
 
 
13306
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
 
13307
        xmlFreeInputStream(input);
 
13308
    }
 
13309
    ctxt->inputNr = 0;
 
13310
    ctxt->input = NULL;
 
13311
 
 
13312
    ctxt->spaceNr = 0;
 
13313
    if (ctxt->spaceTab != NULL) {
 
13314
        ctxt->spaceTab[0] = -1;
 
13315
        ctxt->space = &ctxt->spaceTab[0];
 
13316
    } else {
 
13317
        ctxt->space = NULL;
 
13318
    }
 
13319
 
 
13320
 
 
13321
    ctxt->nodeNr = 0;
 
13322
    ctxt->node = NULL;
 
13323
 
 
13324
    ctxt->nameNr = 0;
 
13325
    ctxt->name = NULL;
 
13326
 
 
13327
    DICT_FREE(ctxt->version);
 
13328
    ctxt->version = NULL;
 
13329
    DICT_FREE(ctxt->encoding);
 
13330
    ctxt->encoding = NULL;
 
13331
    DICT_FREE(ctxt->directory);
 
13332
    ctxt->directory = NULL;
 
13333
    DICT_FREE(ctxt->extSubURI);
 
13334
    ctxt->extSubURI = NULL;
 
13335
    DICT_FREE(ctxt->extSubSystem);
 
13336
    ctxt->extSubSystem = NULL;
 
13337
    if (ctxt->myDoc != NULL)
 
13338
        xmlFreeDoc(ctxt->myDoc);
 
13339
    ctxt->myDoc = NULL;
 
13340
 
 
13341
    ctxt->standalone = -1;
 
13342
    ctxt->hasExternalSubset = 0;
 
13343
    ctxt->hasPErefs = 0;
 
13344
    ctxt->html = 0;
 
13345
    ctxt->external = 0;
 
13346
    ctxt->instate = XML_PARSER_START;
 
13347
    ctxt->token = 0;
 
13348
 
 
13349
    ctxt->wellFormed = 1;
 
13350
    ctxt->nsWellFormed = 1;
 
13351
    ctxt->disableSAX = 0;
 
13352
    ctxt->valid = 1;
 
13353
#if 0
 
13354
    ctxt->vctxt.userData = ctxt;
 
13355
    ctxt->vctxt.error = xmlParserValidityError;
 
13356
    ctxt->vctxt.warning = xmlParserValidityWarning;
 
13357
#endif
 
13358
    ctxt->record_info = 0;
 
13359
    ctxt->nbChars = 0;
 
13360
    ctxt->checkIndex = 0;
 
13361
    ctxt->inSubset = 0;
 
13362
    ctxt->errNo = XML_ERR_OK;
 
13363
    ctxt->depth = 0;
 
13364
    ctxt->charset = XML_CHAR_ENCODING_UTF8;
 
13365
    ctxt->catalogs = NULL;
 
13366
    xmlInitNodeInfoSeq(&ctxt->node_seq);
 
13367
 
 
13368
    if (ctxt->attsDefault != NULL) {
 
13369
        xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
 
13370
        ctxt->attsDefault = NULL;
 
13371
    }
 
13372
    if (ctxt->attsSpecial != NULL) {
 
13373
        xmlHashFree(ctxt->attsSpecial, NULL);
 
13374
        ctxt->attsSpecial = NULL;
 
13375
    }
 
13376
 
 
13377
#ifdef LIBXML_CATALOG_ENABLED
 
13378
    if (ctxt->catalogs != NULL)
 
13379
        xmlCatalogFreeLocal(ctxt->catalogs);
 
13380
#endif
 
13381
    if (ctxt->lastError.code != XML_ERR_OK)
 
13382
        xmlResetError(&ctxt->lastError);
 
13383
}
 
13384
 
 
13385
/**
 
13386
 * xmlCtxtResetPush:
 
13387
 * @ctxt: an XML parser context
 
13388
 * @chunk:  a pointer to an array of chars
 
13389
 * @size:  number of chars in the array
 
13390
 * @filename:  an optional file name or URI
 
13391
 * @encoding:  the document encoding, or NULL
 
13392
 *
 
13393
 * Reset a push parser context
 
13394
 *
 
13395
 * Returns 0 in case of success and 1 in case of error
 
13396
 */
 
13397
int
 
13398
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
 
13399
                 int size, const char *filename, const char *encoding)
 
13400
{
 
13401
    xmlParserInputPtr inputStream;
 
13402
    xmlParserInputBufferPtr buf;
 
13403
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
13404
 
 
13405
    if (ctxt == NULL)
 
13406
        return(1);
 
13407
 
 
13408
    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
 
13409
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
 
13410
 
 
13411
    buf = xmlAllocParserInputBuffer(enc);
 
13412
    if (buf == NULL)
 
13413
        return(1);
 
13414
 
 
13415
    if (ctxt == NULL) {
 
13416
        xmlFreeParserInputBuffer(buf);
 
13417
        return(1);
 
13418
    }
 
13419
 
 
13420
    xmlCtxtReset(ctxt);
 
13421
 
 
13422
    if (ctxt->pushTab == NULL) {
 
13423
        ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
 
13424
                                            sizeof(xmlChar *));
 
13425
        if (ctxt->pushTab == NULL) {
 
13426
            xmlErrMemory(ctxt, NULL);
 
13427
            xmlFreeParserInputBuffer(buf);
 
13428
            return(1);
 
13429
        }
 
13430
    }
 
13431
 
 
13432
    if (filename == NULL) {
 
13433
        ctxt->directory = NULL;
 
13434
    } else {
 
13435
        ctxt->directory = xmlParserGetDirectory(filename);
 
13436
    }
 
13437
 
 
13438
    inputStream = xmlNewInputStream(ctxt);
 
13439
    if (inputStream == NULL) {
 
13440
        xmlFreeParserInputBuffer(buf);
 
13441
        return(1);
 
13442
    }
 
13443
 
 
13444
    if (filename == NULL)
 
13445
        inputStream->filename = NULL;
 
13446
    else
 
13447
        inputStream->filename = (char *)
 
13448
            xmlCanonicPath((const xmlChar *) filename);
 
13449
    inputStream->buf = buf;
 
13450
    inputStream->base = inputStream->buf->buffer->content;
 
13451
    inputStream->cur = inputStream->buf->buffer->content;
 
13452
    inputStream->end =
 
13453
        &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
 
13454
 
 
13455
    inputPush(ctxt, inputStream);
 
13456
 
 
13457
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
 
13458
        (ctxt->input->buf != NULL)) {
 
13459
        int base = ctxt->input->base - ctxt->input->buf->buffer->content;
 
13460
        int cur = ctxt->input->cur - ctxt->input->base;
 
13461
 
 
13462
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
13463
 
 
13464
        ctxt->input->base = ctxt->input->buf->buffer->content + base;
 
13465
        ctxt->input->cur = ctxt->input->base + cur;
 
13466
        ctxt->input->end =
 
13467
            &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->
 
13468
                                               use];
 
13469
#ifdef DEBUG_PUSH
 
13470
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
13471
#endif
 
13472
    }
 
13473
 
 
13474
    if (encoding != NULL) {
 
13475
        xmlCharEncodingHandlerPtr hdlr;
 
13476
 
 
13477
        hdlr = xmlFindCharEncodingHandler(encoding);
 
13478
        if (hdlr != NULL) {
 
13479
            xmlSwitchToEncoding(ctxt, hdlr);
 
13480
        } else {
 
13481
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 
13482
                              "Unsupported encoding %s\n", BAD_CAST encoding);
 
13483
        }
 
13484
    } else if (enc != XML_CHAR_ENCODING_NONE) {
 
13485
        xmlSwitchEncoding(ctxt, enc);
 
13486
    }
 
13487
 
 
13488
    return(0);
 
13489
}
 
13490
 
 
13491
/**
 
13492
 * xmlCtxtUseOptions:
 
13493
 * @ctxt: an XML parser context
 
13494
 * @options:  a combination of xmlParserOption
 
13495
 *
 
13496
 * Applies the options to the parser context
 
13497
 *
 
13498
 * Returns 0 in case of success, the set of unknown or unimplemented options
 
13499
 *         in case of error.
 
13500
 */
 
13501
int
 
13502
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
 
13503
{
 
13504
    if (ctxt == NULL)
 
13505
        return(-1);
 
13506
    if (options & XML_PARSE_RECOVER) {
 
13507
        ctxt->recovery = 1;
 
13508
        options -= XML_PARSE_RECOVER;
 
13509
    } else
 
13510
        ctxt->recovery = 0;
 
13511
    if (options & XML_PARSE_DTDLOAD) {
 
13512
        ctxt->loadsubset = XML_DETECT_IDS;
 
13513
        options -= XML_PARSE_DTDLOAD;
 
13514
    } else
 
13515
        ctxt->loadsubset = 0;
 
13516
    if (options & XML_PARSE_DTDATTR) {
 
13517
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
 
13518
        options -= XML_PARSE_DTDATTR;
 
13519
    }
 
13520
    if (options & XML_PARSE_NOENT) {
 
13521
        ctxt->replaceEntities = 1;
 
13522
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
 
13523
        options -= XML_PARSE_NOENT;
 
13524
    } else
 
13525
        ctxt->replaceEntities = 0;
 
13526
    if (options & XML_PARSE_PEDANTIC) {
 
13527
        ctxt->pedantic = 1;
 
13528
        options -= XML_PARSE_PEDANTIC;
 
13529
    } else
 
13530
        ctxt->pedantic = 0;
 
13531
    if (options & XML_PARSE_NOBLANKS) {
 
13532
        ctxt->keepBlanks = 0;
 
13533
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
 
13534
        options -= XML_PARSE_NOBLANKS;
 
13535
    } else
 
13536
        ctxt->keepBlanks = 1;
 
13537
    if (options & XML_PARSE_DTDVALID) {
 
13538
        ctxt->validate = 1;
 
13539
        if (options & XML_PARSE_NOWARNING)
 
13540
            ctxt->vctxt.warning = NULL;
 
13541
        if (options & XML_PARSE_NOERROR)
 
13542
            ctxt->vctxt.error = NULL;
 
13543
        options -= XML_PARSE_DTDVALID;
 
13544
    } else
 
13545
        ctxt->validate = 0;
 
13546
    if (options & XML_PARSE_NOWARNING) {
 
13547
        ctxt->sax->warning = NULL;
 
13548
        options -= XML_PARSE_NOWARNING;
 
13549
    }
 
13550
    if (options & XML_PARSE_NOERROR) {
 
13551
        ctxt->sax->error = NULL;
 
13552
        ctxt->sax->fatalError = NULL;
 
13553
        options -= XML_PARSE_NOERROR;
 
13554
    }
 
13555
#ifdef LIBXML_SAX1_ENABLED
 
13556
    if (options & XML_PARSE_SAX1) {
 
13557
        ctxt->sax->startElement = xmlSAX2StartElement;
 
13558
        ctxt->sax->endElement = xmlSAX2EndElement;
 
13559
        ctxt->sax->startElementNs = NULL;
 
13560
        ctxt->sax->endElementNs = NULL;
 
13561
        ctxt->sax->initialized = 1;
 
13562
        options -= XML_PARSE_SAX1;
 
13563
    }
 
13564
#endif /* LIBXML_SAX1_ENABLED */
 
13565
    if (options & XML_PARSE_NODICT) {
 
13566
        ctxt->dictNames = 0;
 
13567
        options -= XML_PARSE_NODICT;
 
13568
    } else {
 
13569
        ctxt->dictNames = 1;
 
13570
    }
 
13571
    if (options & XML_PARSE_NOCDATA) {
 
13572
        ctxt->sax->cdataBlock = NULL;
 
13573
        options -= XML_PARSE_NOCDATA;
 
13574
    }
 
13575
    if (options & XML_PARSE_NSCLEAN) {
 
13576
        ctxt->options |= XML_PARSE_NSCLEAN;
 
13577
        options -= XML_PARSE_NSCLEAN;
 
13578
    }
 
13579
    if (options & XML_PARSE_NONET) {
 
13580
        ctxt->options |= XML_PARSE_NONET;
 
13581
        options -= XML_PARSE_NONET;
 
13582
    }
 
13583
    if (options & XML_PARSE_COMPACT) {
 
13584
        ctxt->options |= XML_PARSE_COMPACT;
 
13585
        options -= XML_PARSE_COMPACT;
 
13586
    }
 
13587
    ctxt->linenumbers = 1;
 
13588
    return (options);
 
13589
}
 
13590
 
 
13591
/**
 
13592
 * xmlDoRead:
 
13593
 * @ctxt:  an XML parser context
 
13594
 * @URL:  the base URL to use for the document
 
13595
 * @encoding:  the document encoding, or NULL
 
13596
 * @options:  a combination of xmlParserOption
 
13597
 * @reuse:  keep the context for reuse
 
13598
 *
 
13599
 * Common front-end for the xmlRead functions
 
13600
 * 
 
13601
 * Returns the resulting document tree or NULL
 
13602
 */
 
13603
static xmlDocPtr
 
13604
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
 
13605
          int options, int reuse)
 
13606
{
 
13607
    xmlDocPtr ret;
 
13608
    
 
13609
    xmlCtxtUseOptions(ctxt, options);
 
13610
    if (encoding != NULL) {
 
13611
        xmlCharEncodingHandlerPtr hdlr;
 
13612
 
 
13613
        hdlr = xmlFindCharEncodingHandler(encoding);
 
13614
        if (hdlr != NULL)
 
13615
            xmlSwitchToEncoding(ctxt, hdlr);
 
13616
    }
 
13617
    if ((URL != NULL) && (ctxt->input != NULL) &&
 
13618
        (ctxt->input->filename == NULL))
 
13619
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
 
13620
    xmlParseDocument(ctxt);
 
13621
    if ((ctxt->wellFormed) || ctxt->recovery)
 
13622
        ret = ctxt->myDoc;
 
13623
    else {
 
13624
        ret = NULL;
 
13625
        if (ctxt->myDoc != NULL) {
 
13626
            xmlFreeDoc(ctxt->myDoc);
 
13627
        }
 
13628
    }
 
13629
    ctxt->myDoc = NULL;
 
13630
    if (!reuse) {
 
13631
        xmlFreeParserCtxt(ctxt);
 
13632
    }
 
13633
 
 
13634
    return (ret);
 
13635
}
 
13636
 
 
13637
/**
 
13638
 * xmlReadDoc:
 
13639
 * @cur:  a pointer to a zero terminated string
 
13640
 * @URL:  the base URL to use for the document
 
13641
 * @encoding:  the document encoding, or NULL
 
13642
 * @options:  a combination of xmlParserOption
 
13643
 *
 
13644
 * parse an XML in-memory document and build a tree.
 
13645
 * 
 
13646
 * Returns the resulting document tree
 
13647
 */
 
13648
xmlDocPtr
 
13649
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
 
13650
{
 
13651
    xmlParserCtxtPtr ctxt;
 
13652
 
 
13653
    if (cur == NULL)
 
13654
        return (NULL);
 
13655
 
 
13656
    ctxt = xmlCreateDocParserCtxt(cur);
 
13657
    if (ctxt == NULL)
 
13658
        return (NULL);
 
13659
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
13660
}
 
13661
 
 
13662
/**
 
13663
 * xmlReadFile:
 
13664
 * @filename:  a file or URL
 
13665
 * @encoding:  the document encoding, or NULL
 
13666
 * @options:  a combination of xmlParserOption
 
13667
 *
 
13668
 * parse an XML file from the filesystem or the network.
 
13669
 * 
 
13670
 * Returns the resulting document tree
 
13671
 */
 
13672
xmlDocPtr
 
13673
xmlReadFile(const char *filename, const char *encoding, int options)
 
13674
{
 
13675
    xmlParserCtxtPtr ctxt;
 
13676
 
 
13677
    ctxt = xmlCreateURLParserCtxt(filename, options);
 
13678
    if (ctxt == NULL)
 
13679
        return (NULL);
 
13680
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
 
13681
}
 
13682
 
 
13683
/**
 
13684
 * xmlReadMemory:
 
13685
 * @buffer:  a pointer to a char array
 
13686
 * @size:  the size of the array
 
13687
 * @URL:  the base URL to use for the document
 
13688
 * @encoding:  the document encoding, or NULL
 
13689
 * @options:  a combination of xmlParserOption
 
13690
 *
 
13691
 * parse an XML in-memory document and build a tree.
 
13692
 * 
 
13693
 * Returns the resulting document tree
 
13694
 */
 
13695
xmlDocPtr
 
13696
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
 
13697
{
 
13698
    xmlParserCtxtPtr ctxt;
 
13699
 
 
13700
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
13701
    if (ctxt == NULL)
 
13702
        return (NULL);
 
13703
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
13704
}
 
13705
 
 
13706
/**
 
13707
 * xmlReadFd:
 
13708
 * @fd:  an open file descriptor
 
13709
 * @URL:  the base URL to use for the document
 
13710
 * @encoding:  the document encoding, or NULL
 
13711
 * @options:  a combination of xmlParserOption
 
13712
 *
 
13713
 * parse an XML from a file descriptor and build a tree.
 
13714
 * NOTE that the file descriptor will not be closed when the
 
13715
 *      reader is closed or reset.
 
13716
 * 
 
13717
 * Returns the resulting document tree
 
13718
 */
 
13719
xmlDocPtr
 
13720
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
 
13721
{
 
13722
    xmlParserCtxtPtr ctxt;
 
13723
    xmlParserInputBufferPtr input;
 
13724
    xmlParserInputPtr stream;
 
13725
 
 
13726
    if (fd < 0)
 
13727
        return (NULL);
 
13728
 
 
13729
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 
13730
    if (input == NULL)
 
13731
        return (NULL);
 
13732
    input->closecallback = NULL;
 
13733
    ctxt = xmlNewParserCtxt();
 
13734
    if (ctxt == NULL) {
 
13735
        xmlFreeParserInputBuffer(input);
 
13736
        return (NULL);
 
13737
    }
 
13738
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
13739
    if (stream == NULL) {
 
13740
        xmlFreeParserInputBuffer(input);
 
13741
        xmlFreeParserCtxt(ctxt);
 
13742
        return (NULL);
 
13743
    }
 
13744
    inputPush(ctxt, stream);
 
13745
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
13746
}
 
13747
 
 
13748
/**
 
13749
 * xmlReadIO:
 
13750
 * @ioread:  an I/O read function
 
13751
 * @ioclose:  an I/O close function
 
13752
 * @ioctx:  an I/O handler
 
13753
 * @URL:  the base URL to use for the document
 
13754
 * @encoding:  the document encoding, or NULL
 
13755
 * @options:  a combination of xmlParserOption
 
13756
 *
 
13757
 * parse an XML document from I/O functions and source and build a tree.
 
13758
 * 
 
13759
 * Returns the resulting document tree
 
13760
 */
 
13761
xmlDocPtr
 
13762
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
 
13763
          void *ioctx, const char *URL, const char *encoding, int options)
 
13764
{
 
13765
    xmlParserCtxtPtr ctxt;
 
13766
    xmlParserInputBufferPtr input;
 
13767
    xmlParserInputPtr stream;
 
13768
 
 
13769
    if (ioread == NULL)
 
13770
        return (NULL);
 
13771
 
 
13772
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 
13773
                                         XML_CHAR_ENCODING_NONE);
 
13774
    if (input == NULL)
 
13775
        return (NULL);
 
13776
    ctxt = xmlNewParserCtxt();
 
13777
    if (ctxt == NULL) {
 
13778
        xmlFreeParserInputBuffer(input);
 
13779
        return (NULL);
 
13780
    }
 
13781
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
13782
    if (stream == NULL) {
 
13783
        xmlFreeParserInputBuffer(input);
 
13784
        xmlFreeParserCtxt(ctxt);
 
13785
        return (NULL);
 
13786
    }
 
13787
    inputPush(ctxt, stream);
 
13788
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
13789
}
 
13790
 
 
13791
/**
 
13792
 * xmlCtxtReadDoc:
 
13793
 * @ctxt:  an XML parser context
 
13794
 * @cur:  a pointer to a zero terminated string
 
13795
 * @URL:  the base URL to use for the document
 
13796
 * @encoding:  the document encoding, or NULL
 
13797
 * @options:  a combination of xmlParserOption
 
13798
 *
 
13799
 * parse an XML in-memory document and build a tree.
 
13800
 * This reuses the existing @ctxt parser context
 
13801
 * 
 
13802
 * Returns the resulting document tree
 
13803
 */
 
13804
xmlDocPtr
 
13805
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
 
13806
               const char *URL, const char *encoding, int options)
 
13807
{
 
13808
    xmlParserInputPtr stream;
 
13809
 
 
13810
    if (cur == NULL)
 
13811
        return (NULL);
 
13812
    if (ctxt == NULL)
 
13813
        return (NULL);
 
13814
 
 
13815
    xmlCtxtReset(ctxt);
 
13816
 
 
13817
    stream = xmlNewStringInputStream(ctxt, cur);
 
13818
    if (stream == NULL) {
 
13819
        return (NULL);
 
13820
    }
 
13821
    inputPush(ctxt, stream);
 
13822
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
13823
}
 
13824
 
 
13825
/**
 
13826
 * xmlCtxtReadFile:
 
13827
 * @ctxt:  an XML parser context
 
13828
 * @filename:  a file or URL
 
13829
 * @encoding:  the document encoding, or NULL
 
13830
 * @options:  a combination of xmlParserOption
 
13831
 *
 
13832
 * parse an XML file from the filesystem or the network.
 
13833
 * This reuses the existing @ctxt parser context
 
13834
 * 
 
13835
 * Returns the resulting document tree
 
13836
 */
 
13837
xmlDocPtr
 
13838
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
 
13839
                const char *encoding, int options)
 
13840
{
 
13841
    xmlParserInputPtr stream;
 
13842
 
 
13843
    if (filename == NULL)
 
13844
        return (NULL);
 
13845
    if (ctxt == NULL)
 
13846
        return (NULL);
 
13847
 
 
13848
    xmlCtxtReset(ctxt);
 
13849
 
 
13850
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
 
13851
    if (stream == NULL) {
 
13852
        return (NULL);
 
13853
    }
 
13854
    inputPush(ctxt, stream);
 
13855
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
 
13856
}
 
13857
 
 
13858
/**
 
13859
 * xmlCtxtReadMemory:
 
13860
 * @ctxt:  an XML parser context
 
13861
 * @buffer:  a pointer to a char array
 
13862
 * @size:  the size of the array
 
13863
 * @URL:  the base URL to use for the document
 
13864
 * @encoding:  the document encoding, or NULL
 
13865
 * @options:  a combination of xmlParserOption
 
13866
 *
 
13867
 * parse an XML in-memory document and build a tree.
 
13868
 * This reuses the existing @ctxt parser context
 
13869
 * 
 
13870
 * Returns the resulting document tree
 
13871
 */
 
13872
xmlDocPtr
 
13873
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
 
13874
                  const char *URL, const char *encoding, int options)
 
13875
{
 
13876
    xmlParserInputBufferPtr input;
 
13877
    xmlParserInputPtr stream;
 
13878
 
 
13879
    if (ctxt == NULL)
 
13880
        return (NULL);
 
13881
    if (buffer == NULL)
 
13882
        return (NULL);
 
13883
 
 
13884
    xmlCtxtReset(ctxt);
 
13885
 
 
13886
    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 
13887
    if (input == NULL) {
 
13888
        return(NULL);
 
13889
    }
 
13890
 
 
13891
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
13892
    if (stream == NULL) {
 
13893
        xmlFreeParserInputBuffer(input);
 
13894
        return(NULL);
 
13895
    }
 
13896
 
 
13897
    inputPush(ctxt, stream);
 
13898
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
13899
}
 
13900
 
 
13901
/**
 
13902
 * xmlCtxtReadFd:
 
13903
 * @ctxt:  an XML parser context
 
13904
 * @fd:  an open file descriptor
 
13905
 * @URL:  the base URL to use for the document
 
13906
 * @encoding:  the document encoding, or NULL
 
13907
 * @options:  a combination of xmlParserOption
 
13908
 *
 
13909
 * parse an XML from a file descriptor and build a tree.
 
13910
 * This reuses the existing @ctxt parser context
 
13911
 * NOTE that the file descriptor will not be closed when the
 
13912
 *      reader is closed or reset.
 
13913
 * 
 
13914
 * Returns the resulting document tree
 
13915
 */
 
13916
xmlDocPtr
 
13917
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
 
13918
              const char *URL, const char *encoding, int options)
 
13919
{
 
13920
    xmlParserInputBufferPtr input;
 
13921
    xmlParserInputPtr stream;
 
13922
 
 
13923
    if (fd < 0)
 
13924
        return (NULL);
 
13925
    if (ctxt == NULL)
 
13926
        return (NULL);
 
13927
 
 
13928
    xmlCtxtReset(ctxt);
 
13929
 
 
13930
 
 
13931
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 
13932
    if (input == NULL)
 
13933
        return (NULL);
 
13934
    input->closecallback = NULL;
 
13935
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
13936
    if (stream == NULL) {
 
13937
        xmlFreeParserInputBuffer(input);
 
13938
        return (NULL);
 
13939
    }
 
13940
    inputPush(ctxt, stream);
 
13941
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
13942
}
 
13943
 
 
13944
/**
 
13945
 * xmlCtxtReadIO:
 
13946
 * @ctxt:  an XML parser context
 
13947
 * @ioread:  an I/O read function
 
13948
 * @ioclose:  an I/O close function
 
13949
 * @ioctx:  an I/O handler
 
13950
 * @URL:  the base URL to use for the document
 
13951
 * @encoding:  the document encoding, or NULL
 
13952
 * @options:  a combination of xmlParserOption
 
13953
 *
 
13954
 * parse an XML document from I/O functions and source and build a tree.
 
13955
 * This reuses the existing @ctxt parser context
 
13956
 * 
 
13957
 * Returns the resulting document tree
 
13958
 */
 
13959
xmlDocPtr
 
13960
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
 
13961
              xmlInputCloseCallback ioclose, void *ioctx,
 
13962
              const char *URL,
 
13963
              const char *encoding, int options)
 
13964
{
 
13965
    xmlParserInputBufferPtr input;
 
13966
    xmlParserInputPtr stream;
 
13967
 
 
13968
    if (ioread == NULL)
 
13969
        return (NULL);
 
13970
    if (ctxt == NULL)
 
13971
        return (NULL);
 
13972
 
 
13973
    xmlCtxtReset(ctxt);
 
13974
 
 
13975
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 
13976
                                         XML_CHAR_ENCODING_NONE);
 
13977
    if (input == NULL)
 
13978
        return (NULL);
 
13979
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
13980
    if (stream == NULL) {
 
13981
        xmlFreeParserInputBuffer(input);
 
13982
        return (NULL);
 
13983
    }
 
13984
    inputPush(ctxt, stream);
 
13985
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
13986
}
 
13987
 
 
13988
#define bottom_parser
 
13989
#include "elfgcchack.h"