#define IN_LIBXML
#include "libxml.h"
#if defined(WIN32) && !defined (__CYGWIN__)
#define XML_DIR_SEP '\\'
#else
#define XML_DIR_SEP '/'
#endif
#include <stdlib.h>
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/threads.h>
#include <libxml/globals.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/valid.h>
#include <libxml/entities.h>
#include <libxml/xmlerror.h>
#include <libxml/encoding.h>
#include <libxml/xmlIO.h>
#include <libxml/uri.h>
#ifdef LIBXML_CATALOG_ENABLED
#include <libxml/catalog.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#define MAX_DEPTH 1024
#define XML_PARSER_BIG_BUFFER_SIZE 300
#define XML_PARSER_BUFFER_SIZE 100
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
static const char *xmlW3CPIs[] = {
"xml-stylesheet",
NULL
};
xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
const xmlChar **str);
static int
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
xmlSAXHandlerPtr sax,
void *user_data, int depth, const xmlChar *URL,
const xmlChar *ID, xmlNodePtr *list);
static void
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
xmlNodePtr lastNode);
static int
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
const xmlChar *string, void *user_data, xmlNodePtr *lst);
xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
const xmlChar ** str);
extern int
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
{
if (ctxt->inputNr >= ctxt->inputMax) {
ctxt->inputMax *= 2;
ctxt->inputTab =
(xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
ctxt->inputMax *
sizeof(ctxt->inputTab[0]));
if (ctxt->inputTab == NULL) {
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
return (0);
}
}
ctxt->inputTab[ctxt->inputNr] = value;
ctxt->input = value;
return (ctxt->inputNr++);
}
extern xmlParserInputPtr
inputPop(xmlParserCtxtPtr ctxt)
{
xmlParserInputPtr ret;
if (ctxt->inputNr <= 0)
return (0);
ctxt->inputNr--;
if (ctxt->inputNr > 0)
ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
else
ctxt->input = NULL;
ret = ctxt->inputTab[ctxt->inputNr];
ctxt->inputTab[ctxt->inputNr] = 0;
return (ret);
}
extern int
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
{
if (ctxt->nodeNr >= ctxt->nodeMax) {
ctxt->nodeMax *= 2;
ctxt->nodeTab =
(xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
ctxt->nodeMax *
sizeof(ctxt->nodeTab[0]));
if (ctxt->nodeTab == NULL) {
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
return (0);
}
}
#ifdef MAX_DEPTH
if (ctxt->nodeNr > MAX_DEPTH) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Excessive depth in document: change MAX_DEPTH = %d\n",
MAX_DEPTH);
ctxt->wellFormed = 0;
ctxt->instate = XML_PARSER_EOF;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(0);
}
#endif
ctxt->nodeTab[ctxt->nodeNr] = value;
ctxt->node = value;
return (ctxt->nodeNr++);
}
extern xmlNodePtr
nodePop(xmlParserCtxtPtr ctxt)
{
xmlNodePtr ret;
if (ctxt->nodeNr <= 0)
return (0);
ctxt->nodeNr--;
if (ctxt->nodeNr > 0)
ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
else
ctxt->node = NULL;
ret = ctxt->nodeTab[ctxt->nodeNr];
ctxt->nodeTab[ctxt->nodeNr] = 0;
return (ret);
}
extern int
namePush(xmlParserCtxtPtr ctxt, xmlChar * value)
{
if (ctxt->nameNr >= ctxt->nameMax) {
ctxt->nameMax *= 2;
ctxt->nameTab =
(xmlChar * *)xmlRealloc(ctxt->nameTab,
ctxt->nameMax *
sizeof(ctxt->nameTab[0]));
if (ctxt->nameTab == NULL) {
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
return (0);
}
}
ctxt->nameTab[ctxt->nameNr] = value;
ctxt->name = value;
return (ctxt->nameNr++);
}
extern xmlChar *
namePop(xmlParserCtxtPtr ctxt)
{
xmlChar *ret;
if (ctxt->nameNr <= 0)
return (0);
ctxt->nameNr--;
if (ctxt->nameNr > 0)
ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
else
ctxt->name = NULL;
ret = ctxt->nameTab[ctxt->nameNr];
ctxt->nameTab[ctxt->nameNr] = 0;
return (ret);
}
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
if (ctxt->spaceNr >= ctxt->spaceMax) {
ctxt->spaceMax *= 2;
ctxt->spaceTab = (int *) xmlRealloc(ctxt->spaceTab,
ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
if (ctxt->spaceTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return(0);
}
}
ctxt->spaceTab[ctxt->spaceNr] = val;
ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
return(ctxt->spaceNr++);
}
static int spacePop(xmlParserCtxtPtr ctxt) {
int ret;
if (ctxt->spaceNr <= 0) return(0);
ctxt->spaceNr--;
if (ctxt->spaceNr > 0)
ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
else
ctxt->space = NULL;
ret = ctxt->spaceTab[ctxt->spaceNr];
ctxt->spaceTab[ctxt->spaceNr] = -1;
return(ret);
}
#define RAW (*ctxt->input->cur)
#define CUR (*ctxt->input->cur)
#define NXT(val) ctxt->input->cur[(val)]
#define CUR_PTR ctxt->input->cur
#define SKIP(val) do { \
ctxt->nbChars += (val),ctxt->input->cur += (val); \
if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
if ((*ctxt->input->cur == 0) && \
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
xmlPopInput(ctxt); \
} while (0)
#define SHRINK if (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) \
xmlSHRINK (ctxt);
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
xmlParserInputShrink(ctxt->input);
if ((*ctxt->input->cur == 0) &&
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
xmlPopInput(ctxt);
}
#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \
xmlGROW (ctxt);
static void xmlGROW (xmlParserCtxtPtr ctxt) {
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
if ((*ctxt->input->cur == 0) &&
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
xmlPopInput(ctxt);
}
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
#define NEXT xmlNextChar(ctxt)
#define NEXT1 { \
ctxt->input->cur++; \
ctxt->nbChars++; \
if (*ctxt->input->cur == 0) \
xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
}
#define NEXTL(l) do { \
if (*(ctxt->input->cur) == '\n') { \
ctxt->input->line++; ctxt->input->col = 1; \
} else ctxt->input->col++; \
ctxt->input->cur += l; \
if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
} while (0)
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
#define COPY_BUF(l,b,i,v) \
if (l == 1) b[i++] = (xmlChar) v; \
else i += xmlCopyCharMultiByte(&b[i],v)
int
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
int res = 0;
if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
const xmlChar *cur;
cur = ctxt->input->cur;
while (IS_BLANK(*cur)) {
if (*cur == '\n') {
ctxt->input->line++; ctxt->input->col = 1;
}
cur++;
res++;
if (*cur == 0) {
ctxt->input->cur = cur;
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
cur = ctxt->input->cur;
}
}
ctxt->input->cur = cur;
} else {
int cur;
do {
cur = CUR;
while (IS_BLANK(cur)) {
NEXT;
cur = CUR;
res++;
}
while ((cur == 0) && (ctxt->inputNr > 1) &&
(ctxt->instate != XML_PARSER_COMMENT)) {
xmlPopInput(ctxt);
cur = CUR;
}
if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
} while (IS_BLANK(cur));
}
return(res);
}
xmlChar
xmlPopInput(xmlParserCtxtPtr ctxt) {
if (ctxt->inputNr == 1) return(0);
if (xmlParserDebugEntities)
xmlGenericError(xmlGenericErrorContext,
"Popping input %d\n", ctxt->inputNr);
xmlFreeInputStream(inputPop(ctxt));
if ((*ctxt->input->cur == 0) &&
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
return(xmlPopInput(ctxt));
return(CUR);
}
void
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
if (input == NULL) return;
if (xmlParserDebugEntities) {
if ((ctxt->input != NULL) && (ctxt->input->filename))
xmlGenericError(xmlGenericErrorContext,
"%s(%d): ", ctxt->input->filename,
ctxt->input->line);
xmlGenericError(xmlGenericErrorContext,
"Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
}
inputPush(ctxt, input);
GROW;
}
int
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
unsigned int val = 0;
int count = 0;
if ((RAW == '&') && (NXT(1) == '#') &&
(NXT(2) == 'x')) {
SKIP(3);
GROW;
while (RAW != ';') {
if (count++ > 20) {
count = 0;
GROW;
}
if ((RAW >= '0') && (RAW <= '9'))
val = val * 16 + (CUR - '0');
else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
val = val * 16 + (CUR - 'a') + 10;
else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
val = val * 16 + (CUR - 'A') + 10;
else {
ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseCharRef: invalid hexadecimal value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
val = 0;
break;
}
NEXT;
count++;
}
if (RAW == ';') {
ctxt->nbChars ++;
ctxt->input->cur++;
}
} else if ((RAW == '&') && (NXT(1) == '#')) {
SKIP(2);
GROW;
while (RAW != ';') {
if (count++ > 20) {
count = 0;
GROW;
}
if ((RAW >= '0') && (RAW <= '9'))
val = val * 10 + (CUR - '0');
else {
ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseCharRef: invalid decimal value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
val = 0;
break;
}
NEXT;
count++;
}
if (RAW == ';') {
ctxt->nbChars ++;
ctxt->input->cur++;
}
} else {
ctxt->errNo = XML_ERR_INVALID_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseCharRef: invalid value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (IS_CHAR(val)) {
return(val);
} else {
ctxt->errNo = XML_ERR_INVALID_CHAR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseCharRef: invalid xmlChar value %d\n",
val);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
return(0);
}
static int
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
const xmlChar *ptr;
xmlChar cur;
int val = 0;
if ((str == NULL) || (*str == NULL)) return(0);
ptr = *str;
cur = *ptr;
if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
ptr += 3;
cur = *ptr;
while (cur != ';') {
if ((cur >= '0') && (cur <= '9'))
val = val * 16 + (cur - '0');
else if ((cur >= 'a') && (cur <= 'f'))
val = val * 16 + (cur - 'a') + 10;
else if ((cur >= 'A') && (cur <= 'F'))
val = val * 16 + (cur - 'A') + 10;
else {
ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringCharRef: invalid hexadecimal value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
val = 0;
break;
}
ptr++;
cur = *ptr;
}
if (cur == ';')
ptr++;
} else if ((cur == '&') && (ptr[1] == '#')){
ptr += 2;
cur = *ptr;
while (cur != ';') {
if ((cur >= '0') && (cur <= '9'))
val = val * 10 + (cur - '0');
else {
ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringCharRef: invalid decimal value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
val = 0;
break;
}
ptr++;
cur = *ptr;
}
if (cur == ';')
ptr++;
} else {
ctxt->errNo = XML_ERR_INVALID_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringCharRef: invalid value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(0);
}
*str = ptr;
if (IS_CHAR(val)) {
return(val);
} else {
ctxt->errNo = XML_ERR_INVALID_CHAR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringCharRef: invalid xmlChar value %d\n", val);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
return(0);
}
static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
static xmlParserInputPtr
xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
xmlParserInputPtr input;
xmlChar *buffer;
size_t length;
if (entity == NULL) {
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"internal: xmlNewBlanksWrapperInputStream entity = NULL\n");
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
return(NULL);
}
if (xmlParserDebugEntities)
xmlGenericError(xmlGenericErrorContext,
"new blanks wrapper for entity: %s\n", entity->name);
input = xmlNewInputStream(ctxt);
if (input == NULL) {
return(NULL);
}
length = xmlStrlen(entity->name) + 5;
buffer = xmlMalloc(length);
if (buffer == NULL) {
return(NULL);
}
buffer [0] = ' ';
buffer [1] = '%';
buffer [length-3] = ';';
buffer [length-2] = ' ';
buffer [length-1] = 0;
memcpy(buffer + 2, entity->name, length - 5);
input->free = deallocblankswrapper;
input->base = buffer;
input->cur = buffer;
input->length = length;
input->end = &buffer[length];
return(input);
}
void
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlEntityPtr entity = NULL;
xmlParserInputPtr input;
if (RAW != '%') return;
switch(ctxt->instate) {
case XML_PARSER_CDATA_SECTION:
return;
case XML_PARSER_COMMENT:
return;
case XML_PARSER_START_TAG:
return;
case XML_PARSER_END_TAG:
return;
case XML_PARSER_EOF:
ctxt->errNo = XML_ERR_PEREF_AT_EOF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
case XML_PARSER_PROLOG:
case XML_PARSER_START:
case XML_PARSER_MISC:
ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
case XML_PARSER_ENTITY_DECL:
case XML_PARSER_CONTENT:
case XML_PARSER_ATTRIBUTE_VALUE:
case XML_PARSER_PI:
case XML_PARSER_SYSTEM_LITERAL:
case XML_PARSER_PUBLIC_LITERAL:
return;
case XML_PARSER_EPILOG:
ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
case XML_PARSER_ENTITY_VALUE:
return;
case XML_PARSER_DTD:
if ((ctxt->external == 0) && (ctxt->inputNr == 1))
return;
if (IS_BLANK(NXT(1)) || NXT(1) == 0)
return;
break;
case XML_PARSER_IGNORE:
return;
}
NEXT;
name = xmlParseName(ctxt);
if (xmlParserDebugEntities)
xmlGenericError(xmlGenericErrorContext,
"PEReference: %s\n", name);
if (name == NULL) {
ctxt->errNo = XML_ERR_PEREF_NO_NAME;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "xmlParserHandlePEReference: no name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (RAW == ';') {
NEXT;
if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
if (entity == NULL) {
if ((ctxt->standalone == 1) ||
((ctxt->hasExternalSubset == 0) &&
(ctxt->hasPErefs == 0))) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"PEReference: %%%s; not found\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if ((!ctxt->disableSAX) &&
(ctxt->validate) && (ctxt->vctxt.error != NULL)) {
ctxt->vctxt.error(ctxt->vctxt.userData,
"PEReference: %%%s; not found\n", name);
} else if ((!ctxt->disableSAX) &&
(ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"PEReference: %%%s; not found\n", name);
ctxt->valid = 0;
}
} else if (ctxt->input->free != deallocblankswrapper) {
input = xmlNewBlanksWrapperInputStream(ctxt, entity);
xmlPushInput(ctxt, input);
} else {
if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
(entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
xmlChar start[4];
xmlCharEncoding enc;
input = xmlNewEntityInputStream(ctxt, entity);
xmlPushInput(ctxt, input);
GROW
if (entity->length >= 4) {
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
}
if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
(RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseTextDecl(ctxt);
}
} else {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParserHandlePEReference: %s is not a parameter entity\n",
name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
} else {
ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParserHandlePEReference: expecting ';'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlFree(name);
}
}
#define growBuffer(buffer) { \
buffer##_size *= 2; \
buffer = (xmlChar *) \
xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
if (buffer == NULL) { \
xmlGenericError(xmlGenericErrorContext, "realloc failed"); \
return(NULL); \
} \
}
xmlChar *
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
xmlChar end, xmlChar end2, xmlChar end3) {
xmlChar *buffer = NULL;
int buffer_size = 0;
xmlChar *current = NULL;
xmlEntityPtr ent;
int c,l;
int nbchars = 0;
if (str == NULL)
return(NULL);
if (ctxt->depth > 40) {
ctxt->errNo = XML_ERR_ENTITY_LOOP;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Detected entity reference loop\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
if (buffer == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlStringDecodeEntities: malloc failed");
return(NULL);
}
c = CUR_SCHAR(str, l);
while ((c != 0) && (c != end) &&
(c != end2) && (c != end3)) {
if (c == 0) break;
if ((c == '&') && (str[1] == '#')) {
int val = xmlParseStringCharRef(ctxt, &str);
if (val != 0) {
COPY_BUF(0,buffer,nbchars,val);
}
} else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
if (xmlParserDebugEntities)
xmlGenericError(xmlGenericErrorContext,
"String decoding Entity Reference: %.30s\n",
str);
ent = xmlParseStringEntityRef(ctxt, &str);
if ((ent != NULL) &&
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
if (ent->content != NULL) {
COPY_BUF(0,buffer,nbchars,ent->content[0]);
} else {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"internal error entity has no content\n");
}
} else if ((ent != NULL) && (ent->content != NULL)) {
xmlChar *rep;
ctxt->depth++;
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
if (rep != NULL) {
current = rep;
while (*current != 0) {
buffer[nbchars++] = *current++;
if (nbchars >
buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
}
}
xmlFree(rep);
}
} else if (ent != NULL) {
int i = xmlStrlen(ent->name);
const xmlChar *cur = ent->name;
buffer[nbchars++] = '&';
if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
}
for (;i > 0;i--)
buffer[nbchars++] = *cur++;
buffer[nbchars++] = ';';
}
} else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
if (xmlParserDebugEntities)
xmlGenericError(xmlGenericErrorContext,
"String decoding PE Reference: %.30s\n", str);
ent = xmlParseStringPEReference(ctxt, &str);
if (ent != NULL) {
xmlChar *rep;
ctxt->depth++;
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
if (rep != NULL) {
current = rep;
while (*current != 0) {
buffer[nbchars++] = *current++;
if (nbchars >
buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
}
}
xmlFree(rep);
}
}
} else {
COPY_BUF(l,buffer,nbchars,c);
str += l;
if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
}
}
c = CUR_SCHAR(str, l);
}
buffer[nbchars++] = 0;
return(buffer);
}
xmlChar *
xmlStrndup(const xmlChar *cur, int len) {
xmlChar *ret;
if ((cur == NULL) || (len < 0)) return(NULL);
ret = (xmlChar *) xmlMalloc((len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %ld byte failed\n",
(len + 1) * (long)sizeof(xmlChar));
return(NULL);
}
memcpy(ret, cur, len * sizeof(xmlChar));
ret[len] = 0;
return(ret);
}
xmlChar *
xmlStrdup(const xmlChar *cur) {
const xmlChar *p = cur;
if (cur == NULL) return(NULL);
while (*p != 0) p++;
return(xmlStrndup(cur, p - cur));
}
xmlChar *
xmlCharStrndup(const char *cur, int len) {
int i;
xmlChar *ret;
if ((cur == NULL) || (len < 0)) return(NULL);
ret = (xmlChar *) xmlMalloc((len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext, "malloc of %ld byte failed\n",
(len + 1) * (long)sizeof(xmlChar));
return(NULL);
}
for (i = 0;i < len;i++)
ret[i] = (xmlChar) cur[i];
ret[len] = 0;
return(ret);
}
xmlChar *
xmlCharStrdup(const char *cur) {
const char *p = cur;
if (cur == NULL) return(NULL);
while (*p != '\0') p++;
return(xmlCharStrndup(cur, p - cur));
}
int
xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
register int tmp;
if (str1 == str2) return(0);
if (str1 == NULL) return(-1);
if (str2 == NULL) return(1);
do {
tmp = *str1++ - *str2;
if (tmp != 0) return(tmp);
} while (*str2++ != 0);
return 0;
}
int
xmlStrEqual(const xmlChar *str1, const xmlChar *str2) {
if (str1 == str2) return(1);
if (str1 == NULL) return(0);
if (str2 == NULL) return(0);
do {
if (*str1++ != *str2) return(0);
} while (*str2++);
return(1);
}
int
xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
register int tmp;
if (len <= 0) return(0);
if (str1 == str2) return(0);
if (str1 == NULL) return(-1);
if (str2 == NULL) return(1);
do {
tmp = *str1++ - *str2;
if (tmp != 0 || --len == 0) return(tmp);
} while (*str2++ != 0);
return 0;
}
static const xmlChar casemap[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
int
xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) {
register int tmp;
if (str1 == str2) return(0);
if (str1 == NULL) return(-1);
if (str2 == NULL) return(1);
do {
tmp = casemap[*str1++] - casemap[*str2];
if (tmp != 0) return(tmp);
} while (*str2++ != 0);
return 0;
}
int
xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len) {
register int tmp;
if (len <= 0) return(0);
if (str1 == str2) return(0);
if (str1 == NULL) return(-1);
if (str2 == NULL) return(1);
do {
tmp = casemap[*str1++] - casemap[*str2];
if (tmp != 0 || --len == 0) return(tmp);
} while (*str2++ != 0);
return 0;
}
const xmlChar *
xmlStrchr(const xmlChar *str, xmlChar val) {
if (str == NULL) return(NULL);
while (*str != 0) {
if (*str == val) return((xmlChar *) str);
str++;
}
return(NULL);
}
const xmlChar *
xmlStrstr(const xmlChar *str, const xmlChar *val) {
int n;
if (str == NULL) return(NULL);
if (val == NULL) return(NULL);
n = xmlStrlen(val);
if (n == 0) return(str);
while (*str != 0) {
if (*str == *val) {
if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
}
str++;
}
return(NULL);
}
const xmlChar *
xmlStrcasestr(const xmlChar *str, xmlChar *val) {
int n;
if (str == NULL) return(NULL);
if (val == NULL) return(NULL);
n = xmlStrlen(val);
if (n == 0) return(str);
while (*str != 0) {
if (casemap[*str] == casemap[*val])
if (!xmlStrncasecmp(str, val, n)) return(str);
str++;
}
return(NULL);
}
xmlChar *
xmlStrsub(const xmlChar *str, int start, int len) {
int i;
if (str == NULL) return(NULL);
if (start < 0) return(NULL);
if (len < 0) return(NULL);
for (i = 0;i < start;i++) {
if (*str == 0) return(NULL);
str++;
}
if (*str == 0) return(NULL);
return(xmlStrndup(str, len));
}
int
xmlStrlen(const xmlChar *str) {
int len = 0;
if (str == NULL) return(0);
while (*str != 0) {
str++;
len++;
}
return(len);
}
xmlChar *
xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
int size;
xmlChar *ret;
if ((add == NULL) || (len == 0))
return(cur);
if (cur == NULL)
return(xmlStrndup(add, len));
size = xmlStrlen(cur);
ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlStrncat: realloc of %ld byte failed\n",
(size + len + 1) * (long)sizeof(xmlChar));
return(cur);
}
memcpy(&ret[size], add, len * sizeof(xmlChar));
ret[size + len] = 0;
return(ret);
}
xmlChar *
xmlStrcat(xmlChar *cur, const xmlChar *add) {
const xmlChar *p = add;
if (add == NULL) return(cur);
if (cur == NULL)
return(xmlStrdup(add));
while (*p != 0) p++;
return(xmlStrncat(cur, add, p - add));
}
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
int i, ret;
xmlNodePtr lastChild;
if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
return(0);
if (*(ctxt->space) == 1)
return(0);
for (i = 0;i < len;i++)
if (!(IS_BLANK(str[i]))) return(0);
if (ctxt->node == NULL) return(0);
if (ctxt->myDoc != NULL) {
ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
if (ret == 0) return(1);
if (ret == 1) return(0);
}
if (RAW != '<') return(0);
if ((ctxt->node->children == NULL) &&
(RAW == '<') && (NXT(1) == '/')) return(0);
lastChild = xmlGetLastChild(ctxt->node);
if (lastChild == NULL) {
if ((ctxt->node->type != XML_ELEMENT_NODE) &&
(ctxt->node->content != NULL)) return(0);
} else if (xmlNodeIsText(lastChild))
return(0);
else if ((ctxt->node->children != NULL) &&
(xmlNodeIsText(ctxt->node->children)))
return(0);
return(1);
}
xmlChar *
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
xmlChar buf[XML_MAX_NAMELEN + 5];
xmlChar *buffer = NULL;
int len = 0;
int max = XML_MAX_NAMELEN;
xmlChar *ret = NULL;
const xmlChar *cur = name;
int c;
*prefix = NULL;
#ifndef XML_XML_NAMESPACE
if ((cur[0] == 'x') && (cur[1] == 'm') &&
(cur[2] == 'l') && (cur[3] == ':'))
return(xmlStrdup(name));
#endif
if (cur[0] == ':')
return(xmlStrdup(name));
c = *cur++;
while ((c != 0) && (c != ':') && (len < max)) {
buf[len++] = c;
c = *cur++;
}
if (len >= max) {
max = len * 2;
buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlSplitQName: out of memory\n");
return(NULL);
}
memcpy(buffer, buf, len);
while ((c != 0) && (c != ':')) {
if (len + 10 > max) {
max *= 2;
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlSplitQName: out of memory\n");
return(NULL);
}
}
buffer[len++] = c;
c = *cur++;
}
buffer[len] = 0;
}
if (buffer == NULL)
ret = xmlStrndup(buf, len);
else {
ret = buffer;
buffer = NULL;
max = XML_MAX_NAMELEN;
}
if (c == ':') {
c = *cur;
if (c == 0) return(ret);
*prefix = ret;
len = 0;
if (!(((c >= 0x61) && (c <= 0x7A)) ||
((c >= 0x41) && (c <= 0x5A)) ||
(c == '_') || (c == ':'))) {
int l;
int first = CUR_SCHAR(cur, l);
if (!IS_LETTER(first) && (first != '_')) {
if ((ctxt != NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Name %s is not XML Namespace compliant\n",
name);
}
}
cur++;
while ((c != 0) && (len < max)) {
buf[len++] = c;
c = *cur++;
}
if (len >= max) {
max = len * 2;
buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt != NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlSplitQName: out of memory\n");
return(NULL);
}
memcpy(buffer, buf, len);
while (c != 0) {
if (len + 10 > max) {
max *= 2;
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt != NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlSplitQName: out of memory\n");
return(NULL);
}
}
buffer[len++] = c;
c = *cur++;
}
buffer[len] = 0;
}
if (buffer == NULL)
ret = xmlStrndup(buf, len);
else {
ret = buffer;
}
}
return(ret);
}
static xmlChar * xmlParseNameComplex(xmlParserCtxtPtr ctxt);
xmlChar *
xmlParseName(xmlParserCtxtPtr ctxt) {
const xmlChar *in;
xmlChar *ret;
int count = 0;
GROW;
in = ctxt->input->cur;
if (((*in >= 0x61) && (*in <= 0x7A)) ||
((*in >= 0x41) && (*in <= 0x5A)) ||
(*in == '_') || (*in == ':')) {
in++;
while (((*in >= 0x61) && (*in <= 0x7A)) ||
((*in >= 0x41) && (*in <= 0x5A)) ||
((*in >= 0x30) && (*in <= 0x39)) ||
(*in == '_') || (*in == '-') ||
(*in == ':') || (*in == '.'))
in++;
if ((*in > 0) && (*in < 0x80)) {
count = in - ctxt->input->cur;
ret = xmlStrndup(ctxt->input->cur, count);
ctxt->input->cur = in;
return(ret);
}
}
return(xmlParseNameComplex(ctxt));
}
static xmlChar *
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
const xmlChar *cmp = other;
const xmlChar *in;
xmlChar *ret;
GROW;
in = ctxt->input->cur;
while (*in != 0 && *in == *cmp) {
++in;
++cmp;
}
if (*cmp == 0 && (*in == '>' || IS_BLANK (*in))) {
ctxt->input->cur = in;
return (xmlChar*) 1;
}
ret = xmlParseName (ctxt);
if (ret != 0 && xmlStrEqual (ret, other)) {
xmlFree (ret);
return (xmlChar*) 1;
}
return ret;
}
static xmlChar *
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
xmlChar buf[XML_MAX_NAMELEN + 5];
int len = 0, l;
int c;
int count = 0;
GROW;
c = CUR_CHAR(l);
if ((c == ' ') || (c == '>') || (c == '/') ||
(!IS_LETTER(c) && (c != '_') &&
(c != ':'))) {
return(NULL);
}
while ((c != ' ') && (c != '>') && (c != '/') &&
((IS_LETTER(c)) || (IS_DIGIT(c)) ||
(c == '.') || (c == '-') ||
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c)))) {
if (count++ > 100) {
count = 0;
GROW;
}
COPY_BUF(l,buf,len,c);
NEXTL(l);
c = CUR_CHAR(l);
if (len >= XML_MAX_NAMELEN) {
xmlChar *buffer;
int max = len * 2;
buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseNameComplex: out of memory\n");
return(NULL);
}
memcpy(buffer, buf, len);
while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
(c == '.') || (c == '-') ||
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
if (count++ > 100) {
count = 0;
GROW;
}
if (len + 10 > max) {
max *= 2;
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseNameComplex: out of memory\n");
return(NULL);
}
}
COPY_BUF(l,buffer,len,c);
NEXTL(l);
c = CUR_CHAR(l);
}
buffer[len] = 0;
return(buffer);
}
}
return(xmlStrndup(buf, len));
}
static xmlChar *
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
xmlChar buf[XML_MAX_NAMELEN + 5];
const xmlChar *cur = *str;
int len = 0, l;
int c;
c = CUR_SCHAR(cur, l);
if (!IS_LETTER(c) && (c != '_') &&
(c != ':')) {
return(NULL);
}
while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
(c == '.') || (c == '-') ||
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
COPY_BUF(l,buf,len,c);
cur += l;
c = CUR_SCHAR(cur, l);
if (len >= XML_MAX_NAMELEN) {
xmlChar *buffer;
int max = len * 2;
buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringName: out of memory\n");
return(NULL);
}
memcpy(buffer, buf, len);
while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
(c == '.') || (c == '-') ||
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
if (len + 10 > max) {
max *= 2;
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringName: out of memory\n");
return(NULL);
}
}
COPY_BUF(l,buffer,len,c);
cur += l;
c = CUR_SCHAR(cur, l);
}
buffer[len] = 0;
*str = cur;
return(buffer);
}
}
*str = cur;
return(xmlStrndup(buf, len));
}
xmlChar *
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
xmlChar buf[XML_MAX_NAMELEN + 5];
int len = 0, l;
int c;
int count = 0;
GROW;
c = CUR_CHAR(l);
while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
(c == '.') || (c == '-') ||
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
if (count++ > 100) {
count = 0;
GROW;
}
COPY_BUF(l,buf,len,c);
NEXTL(l);
c = CUR_CHAR(l);
if (len >= XML_MAX_NAMELEN) {
xmlChar *buffer;
int max = len * 2;
buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseNmtoken: out of memory\n");
return(NULL);
}
memcpy(buffer, buf, len);
while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
(c == '.') || (c == '-') ||
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
if (count++ > 100) {
count = 0;
GROW;
}
if (len + 10 > max) {
max *= 2;
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseNmtoken: out of memory\n");
return(NULL);
}
}
COPY_BUF(l,buffer,len,c);
NEXTL(l);
c = CUR_CHAR(l);
}
buffer[len] = 0;
return(buffer);
}
}
if (len == 0)
return(NULL);
return(xmlStrndup(buf, len));
}
xmlChar *
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
xmlChar *buf = NULL;
int len = 0;
int size = XML_PARSER_BUFFER_SIZE;
int c, l;
xmlChar stop;
xmlChar *ret = NULL;
const xmlChar *cur = NULL;
xmlParserInputPtr input;
if (RAW == '"') stop = '"';
else if (RAW == '\'') stop = '\'';
else {
ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
return(NULL);
}
ctxt->instate = XML_PARSER_ENTITY_VALUE;
input = ctxt->input;
GROW;
NEXT;
c = CUR_CHAR(l);
while ((IS_CHAR(c)) && ((c != stop) ||
(ctxt->input != input))) {
if (len + 5 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
return(NULL);
}
}
COPY_BUF(l,buf,len,c);
NEXTL(l);
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
GROW;
c = CUR_CHAR(l);
if (c == 0) {
GROW;
c = CUR_CHAR(l);
}
}
buf[len] = 0;
cur = buf;
while (*cur != 0) {
if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
xmlChar *name;
xmlChar tmp = *cur;
cur++;
name = xmlParseStringName(ctxt, &cur);
if ((name == NULL) || (*cur != ';')) {
ctxt->errNo = XML_ERR_ENTITY_CHAR_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"EntityValue: '%c' forbidden except for entities references\n",
tmp);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if ((tmp == '%') && (ctxt->inSubset == 1) &&
(ctxt->inputNr == 1)) {
ctxt->errNo = XML_ERR_ENTITY_PE_INTERNAL;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"EntityValue: PEReferences forbidden in internal subset\n",
tmp);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (name != NULL)
xmlFree(name);
}
cur++;
}
if (c != stop) {
ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
xmlFree(buf);
} else {
NEXT;
ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
0, 0, 0);
if (orig != NULL)
*orig = buf;
else
xmlFree(buf);
}
return(ret);
}
xmlChar *
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt);
xmlChar *
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
xmlChar limit = 0;
const xmlChar *in = NULL;
xmlChar *ret = NULL;
SHRINK;
GROW;
in = (xmlChar *) CUR_PTR;
if (*in != '"' && *in != '\'') {
ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
limit = *in;
++in;
while (*in != limit && *in >= 0x20 && *in <= 0x7f &&
*in != '&' && *in != '<'
) {
++in;
}
if (*in != limit) {
return xmlParseAttValueComplex(ctxt);
}
++in;
ret = xmlStrndup (CUR_PTR + 1, in - CUR_PTR - 2);
CUR_PTR = in;
return ret;
}
xmlChar *
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt) {
xmlChar limit = 0;
xmlChar *buf = NULL;
int len = 0;
int buf_size = 0;
int c, l;
xmlChar *current = NULL;
xmlEntityPtr ent;
SHRINK;
if (NXT(0) == '"') {
ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
limit = '"';
NEXT;
} else if (NXT(0) == '\'') {
limit = '\'';
ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
NEXT;
} else {
ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
buf_size = XML_PARSER_BUFFER_SIZE;
buf = (xmlChar *) xmlMalloc(buf_size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlParseAttValue: malloc failed");
return(NULL);
}
c = CUR_CHAR(l);
while ((NXT(0) != limit) &&
(c != '<')) {
if (c == 0) break;
if (c == '&') {
if (NXT(1) == '#') {
int val = xmlParseCharRef(ctxt);
if (val == '&') {
if (ctxt->replaceEntities) {
if (len > buf_size - 10) {
growBuffer(buf);
}
buf[len++] = '&';
} else {
static xmlChar buffer[6] = "&";
if (len > buf_size - 10) {
growBuffer(buf);
}
current = &buffer[0];
while (*current != 0) {
buf[len++] = *current++;
}
}
} else {
if (len > buf_size - 10) {
growBuffer(buf);
}
len += xmlCopyChar(0, &buf[len], val);
}
} else {
ent = xmlParseEntityRef(ctxt);
if ((ent != NULL) &&
(ctxt->replaceEntities != 0)) {
xmlChar *rep;
if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0, 0);
if (rep != NULL) {
current = rep;
while (*current != 0) {
buf[len++] = *current++;
if (len > buf_size - 10) {
growBuffer(buf);
}
}
xmlFree(rep);
}
} else {
if (len > buf_size - 10) {
growBuffer(buf);
}
if (ent->content != NULL)
buf[len++] = ent->content[0];
}
} else if (ent != NULL) {
int i = xmlStrlen(ent->name);
const xmlChar *cur = ent->name;
if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
(ent->content != NULL)) {
xmlChar *rep;
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0, 0);
if (rep != NULL)
xmlFree(rep);
}
buf[len++] = '&';
if (len > buf_size - i - 10) {
growBuffer(buf);
}
for (;i > 0;i--)
buf[len++] = *cur++;
buf[len++] = ';';
}
}
} else {
if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
COPY_BUF(l,buf,len,0x20);
if (len > buf_size - 10) {
growBuffer(buf);
}
} else {
COPY_BUF(l,buf,len,c);
if (len > buf_size - 10) {
growBuffer(buf);
}
}
NEXTL(l);
}
GROW;
c = CUR_CHAR(l);
}
buf[len++] = 0;
if (RAW == '<') {
ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Unescaped '<' not allowed in attributes values\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (RAW != limit) {
ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
return(buf);
}
xmlChar *
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = XML_PARSER_BUFFER_SIZE;
int cur, l;
xmlChar stop;
int state = ctxt->instate;
int count = 0;
SHRINK;
if (RAW == '"') {
NEXT;
stop = '"';
} else if (RAW == '\'') {
NEXT;
stop = '\'';
} else {
ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"SystemLiteral \" or ' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
return(NULL);
}
ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
cur = CUR_CHAR(l);
while ((IS_CHAR(cur)) && (cur != stop)) {
if (len + 5 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
ctxt->instate = (xmlParserInputState) state;
return(NULL);
}
}
count++;
if (count > 50) {
GROW;
count = 0;
}
COPY_BUF(l,buf,len,cur);
NEXTL(l);
cur = CUR_CHAR(l);
if (cur == 0) {
GROW;
SHRINK;
cur = CUR_CHAR(l);
}
}
buf[len] = 0;
ctxt->instate = (xmlParserInputState) state;
if (!IS_CHAR(cur)) {
ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
NEXT;
}
return(buf);
}
xmlChar *
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = XML_PARSER_BUFFER_SIZE;
xmlChar cur;
xmlChar stop;
int count = 0;
xmlParserInputState oldstate = ctxt->instate;
SHRINK;
if (RAW == '"') {
NEXT;
stop = '"';
} else if (RAW == '\'') {
NEXT;
stop = '\'';
} else {
ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"SystemLiteral \" or ' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
return(NULL);
}
ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
cur = CUR;
while ((IS_PUBIDCHAR(cur)) && (cur != stop)) {
if (len + 1 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
return(NULL);
}
}
buf[len++] = cur;
count++;
if (count > 50) {
GROW;
count = 0;
}
NEXT;
cur = CUR;
if (cur == 0) {
GROW;
SHRINK;
cur = CUR;
}
}
buf[len] = 0;
if (cur != stop) {
ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
NEXT;
}
ctxt->instate = oldstate;
return(buf);
}
void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
void
xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
const xmlChar *in;
int nbchar = 0;
int line = ctxt->input->line;
int col = ctxt->input->col;
SHRINK;
GROW;
if (!cdata) {
in = ctxt->input->cur;
do {
get_more:
while (((*in >= 0x20) && (*in != '<') && (*in != ']') &&
(*in != '&') && (*in <= 0x7F)) || (*in == 0x09))
in++;
if (*in == 0xA) {
ctxt->input->line++;
in++;
while (*in == 0xA) {
ctxt->input->line++;
in++;
}
goto get_more;
}
if (*in == ']') {
if ((in[1] == ']') && (in[2] == '>')) {
ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Sequence ']]>' not allowed in content\n");
ctxt->input->cur = in;
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
in++;
goto get_more;
}
nbchar = in - ctxt->input->cur;
if (nbchar > 0) {
if (IS_BLANK(*ctxt->input->cur)) {
const xmlChar *tmp = ctxt->input->cur;
ctxt->input->cur = in;
if (areBlanks(ctxt, tmp, nbchar)) {
if (ctxt->sax->ignorableWhitespace != NULL)
ctxt->sax->ignorableWhitespace(ctxt->userData,
tmp, nbchar);
} else {
if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData,
tmp, nbchar);
}
line = ctxt->input->line;
col = ctxt->input->col;
} else {
if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData,
ctxt->input->cur, nbchar);
line = ctxt->input->line;
col = ctxt->input->col;
}
}
ctxt->input->cur = in;
if (*in == 0xD) {
in++;
if (*in == 0xA) {
ctxt->input->cur = in;
in++;
ctxt->input->line++;
continue;
}
in--;
}
if (*in == '<') {
return;
}
if (*in == '&') {
return;
}
SHRINK;
GROW;
in = ctxt->input->cur;
} while ((*in >= 0x20) && (*in <= 0x7F));
nbchar = 0;
}
ctxt->input->line = line;
ctxt->input->col = col;
xmlParseCharDataComplex(ctxt, cdata);
}
void
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
int nbchar = 0;
int cur, l;
int count = 0;
SHRINK;
GROW;
cur = CUR_CHAR(l);
while ((cur != '<') &&
(cur != '&') &&
(IS_CHAR(cur))) {
if ((cur == ']') && (NXT(1) == ']') &&
(NXT(2) == '>')) {
if (cdata) break;
else {
ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Sequence ']]>' not allowed in content\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
COPY_BUF(l,buf,nbchar,cur);
if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
if (areBlanks(ctxt, buf, nbchar)) {
if (ctxt->sax->ignorableWhitespace != NULL)
ctxt->sax->ignorableWhitespace(ctxt->userData,
buf, nbchar);
} else {
if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData, buf, nbchar);
}
}
nbchar = 0;
}
count++;
if (count > 50) {
GROW;
count = 0;
}
NEXTL(l);
cur = CUR_CHAR(l);
}
if (nbchar != 0) {
if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
if (areBlanks(ctxt, buf, nbchar)) {
if (ctxt->sax->ignorableWhitespace != NULL)
ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
} else {
if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData, buf, nbchar);
}
}
}
}
xmlChar *
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
xmlChar *URI = NULL;
SHRINK;
*publicID = NULL;
if ((RAW == 'S') && (NXT(1) == 'Y') &&
(NXT(2) == 'S') && (NXT(3) == 'T') &&
(NXT(4) == 'E') && (NXT(5) == 'M')) {
SKIP(6);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after 'SYSTEM'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
URI = xmlParseSystemLiteral(ctxt);
if (URI == NULL) {
ctxt->errNo = XML_ERR_URI_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseExternalID: SYSTEM, no URI\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
} else if ((RAW == 'P') && (NXT(1) == 'U') &&
(NXT(2) == 'B') && (NXT(3) == 'L') &&
(NXT(4) == 'I') && (NXT(5) == 'C')) {
SKIP(6);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after 'PUBLIC'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
*publicID = xmlParsePubidLiteral(ctxt);
if (*publicID == NULL) {
ctxt->errNo = XML_ERR_PUBID_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseExternalID: PUBLIC, no Public Identifier\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (strict) {
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the Public Identifier\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
} else {
const xmlChar *ptr;
GROW;
ptr = CUR_PTR;
if (!IS_BLANK(*ptr)) return(NULL);
while (IS_BLANK(*ptr)) ptr++;
if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
}
SKIP_BLANKS;
URI = xmlParseSystemLiteral(ctxt);
if (URI == NULL) {
ctxt->errNo = XML_ERR_URI_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseExternalID: PUBLIC, no URI\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
return(URI);
}
void
xmlParseComment(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len;
int size = XML_PARSER_BUFFER_SIZE;
int q, ql;
int r, rl;
int cur, l;
xmlParserInputState state;
xmlParserInputPtr input = ctxt->input;
int count = 0;
if ((RAW != '<') || (NXT(1) != '!') ||
(NXT(2) != '-') || (NXT(3) != '-')) return;
state = ctxt->instate;
ctxt->instate = XML_PARSER_COMMENT;
SHRINK;
SKIP(4);
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
ctxt->instate = state;
return;
}
q = CUR_CHAR(ql);
NEXTL(ql);
r = CUR_CHAR(rl);
NEXTL(rl);
cur = CUR_CHAR(l);
len = 0;
while (IS_CHAR(cur) &&
((cur != '>') ||
(r != '-') || (q != '-'))) {
if ((r == '-') && (q == '-')) {
ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Comment must not contain '--' (double-hyphen)`\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (len + 5 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
ctxt->instate = state;
return;
}
}
COPY_BUF(ql,buf,len,q);
q = r;
ql = rl;
r = cur;
rl = l;
count++;
if (count > 50) {
GROW;
count = 0;
}
NEXTL(l);
cur = CUR_CHAR(l);
if (cur == 0) {
SHRINK;
GROW;
cur = CUR_CHAR(l);
}
}
buf[len] = 0;
if (!IS_CHAR(cur)) {
ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Comment not terminated \n<!--%.50s\n", buf);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
xmlFree(buf);
} else {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Comment doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->comment(ctxt->userData, buf);
xmlFree(buf);
}
ctxt->instate = state;
}
xmlChar *
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
xmlChar *name;
name = xmlParseName(ctxt);
if ((name != NULL) &&
((name[0] == 'x') || (name[0] == 'X')) &&
((name[1] == 'm') || (name[1] == 'M')) &&
((name[2] == 'l') || (name[2] == 'L'))) {
int i;
if ((name[0] == 'x') && (name[1] == 'm') &&
(name[2] == 'l') && (name[3] == 0)) {
ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML declaration allowed only at the start of the document\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(name);
} else if (name[3] == 0) {
ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Invalid PI name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(name);
}
for (i = 0;;i++) {
if (xmlW3CPIs[i] == NULL) break;
if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
return(name);
}
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) {
ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
ctxt->sax->warning(ctxt->userData,
"xmlParsePITarget: invalid name prefix 'xml'\n");
}
}
return(name);
}
#ifdef LIBXML_CATALOG_ENABLED
static void
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
xmlChar *URL = NULL;
const xmlChar *tmp, *base;
xmlChar marker;
tmp = catalog;
while (IS_BLANK(*tmp)) tmp++;
if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
goto error;
tmp += 7;
while (IS_BLANK(*tmp)) tmp++;
if (*tmp != '=') {
return;
}
tmp++;
while (IS_BLANK(*tmp)) tmp++;
marker = *tmp;
if ((marker != '\'') && (marker != '"'))
goto error;
tmp++;
base = tmp;
while ((*tmp != 0) && (*tmp != marker)) tmp++;
if (*tmp == 0)
goto error;
URL = xmlStrndup(base, tmp - base);
tmp++;
while (IS_BLANK(*tmp)) tmp++;
if (*tmp != 0)
goto error;
if (URL != NULL) {
ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
xmlFree(URL);
}
return;
error:
ctxt->errNo = XML_WAR_CATALOG_PI;
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"Catalog PI syntax error: %s\n", catalog);
if (URL != NULL)
xmlFree(URL);
}
#endif
void
xmlParsePI(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = XML_PARSER_BUFFER_SIZE;
int cur, l;
xmlChar *target;
xmlParserInputState state;
int count = 0;
if ((RAW == '<') && (NXT(1) == '?')) {
xmlParserInputPtr input = ctxt->input;
state = ctxt->instate;
ctxt->instate = XML_PARSER_PI;
SKIP(2);
SHRINK;
target = xmlParsePITarget(ctxt);
if (target != NULL) {
if ((RAW == '?') && (NXT(1) == '>')) {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"PI declaration doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP(2);
if ((ctxt->sax) && (!ctxt->disableSAX) &&
(ctxt->sax->processingInstruction != NULL))
ctxt->sax->processingInstruction(ctxt->userData,
target, NULL);
ctxt->instate = state;
xmlFree(target);
return;
}
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
ctxt->instate = state;
return;
}
cur = CUR;
if (!IS_BLANK(cur)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParsePI: PI %s space expected\n", target);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
cur = CUR_CHAR(l);
while (IS_CHAR(cur) &&
((cur != '?') || (NXT(1) != '>'))) {
if (len + 5 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
ctxt->instate = state;
return;
}
}
count++;
if (count > 50) {
GROW;
count = 0;
}
COPY_BUF(l,buf,len,cur);
NEXTL(l);
cur = CUR_CHAR(l);
if (cur == 0) {
SHRINK;
GROW;
cur = CUR_CHAR(l);
}
}
buf[len] = 0;
if (cur != '?') {
ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParsePI: PI %s never end ...\n", target);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"PI declaration doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP(2);
#ifdef LIBXML_CATALOG_ENABLED
if (((state == XML_PARSER_MISC) ||
(state == XML_PARSER_START)) &&
(xmlStrEqual(target, XML_CATALOG_PI))) {
xmlCatalogAllow allow = xmlCatalogGetDefaults();
if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
(allow == XML_CATA_ALLOW_ALL))
xmlParseCatalogPI(ctxt, buf);
}
#endif
if ((ctxt->sax) && (!ctxt->disableSAX) &&
(ctxt->sax->processingInstruction != NULL))
ctxt->sax->processingInstruction(ctxt->userData,
target, buf);
}
xmlFree(buf);
xmlFree(target);
} else {
ctxt->errNo = XML_ERR_PI_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParsePI : no target name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
ctxt->instate = state;
}
}
void
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlChar *Pubid;
xmlChar *Systemid;
if ((RAW == '<') && (NXT(1) == '!') &&
(NXT(2) == 'N') && (NXT(3) == 'O') &&
(NXT(4) == 'T') && (NXT(5) == 'A') &&
(NXT(6) == 'T') && (NXT(7) == 'I') &&
(NXT(8) == 'O') && (NXT(9) == 'N')) {
xmlParserInputPtr input = ctxt->input;
SHRINK;
SKIP(10);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after '<!NOTATION'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
SKIP_BLANKS;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"NOTATION: Name expected here\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the NOTATION name'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
SKIP_BLANKS;
Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
SKIP_BLANKS;
if (RAW == '>') {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Notation declaration doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->notationDecl != NULL))
ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
} else {
ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"'>' required to close NOTATION declaration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlFree(name);
if (Systemid != NULL) xmlFree(Systemid);
if (Pubid != NULL) xmlFree(Pubid);
}
}
void
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
xmlChar *name = NULL;
xmlChar *value = NULL;
xmlChar *URI = NULL, *literal = NULL;
xmlChar *ndata = NULL;
int isParameter = 0;
xmlChar *orig = NULL;
int skipped;
GROW;
if ((RAW == '<') && (NXT(1) == '!') &&
(NXT(2) == 'E') && (NXT(3) == 'N') &&
(NXT(4) == 'T') && (NXT(5) == 'I') &&
(NXT(6) == 'T') && (NXT(7) == 'Y')) {
xmlParserInputPtr input = ctxt->input;
SHRINK;
SKIP(8);
skipped = SKIP_BLANKS;
if (skipped == 0) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after '<!ENTITY'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (RAW == '%') {
NEXT;
skipped = SKIP_BLANKS;
if (skipped == 0) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after '%'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
isParameter = 1;
}
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
skipped = SKIP_BLANKS;
if (skipped == 0) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the entity name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
ctxt->instate = XML_PARSER_ENTITY_DECL;
if (isParameter) {
if ((RAW == '"') || (RAW == '\'')) {
value = xmlParseEntityValue(ctxt, &orig);
if (value) {
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
ctxt->sax->entityDecl(ctxt->userData, name,
XML_INTERNAL_PARAMETER_ENTITY,
NULL, NULL, value);
}
} else {
URI = xmlParseExternalID(ctxt, &literal, 1);
if ((URI == NULL) && (literal == NULL)) {
ctxt->errNo = XML_ERR_VALUE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity value required\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (URI) {
xmlURIPtr uri;
uri = xmlParseURI((const char *) URI);
if (uri == NULL) {
ctxt->errNo = XML_ERR_INVALID_URI;
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Invalid URI: %s\n", URI);
} else {
if (uri->fragment != NULL) {
ctxt->errNo = XML_ERR_URI_FRAGMENT;
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Fragment not allowed: %s\n", URI);
ctxt->wellFormed = 0;
} else {
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) &&
(ctxt->sax->entityDecl != NULL))
ctxt->sax->entityDecl(ctxt->userData, name,
XML_EXTERNAL_PARAMETER_ENTITY,
literal, URI, NULL);
}
xmlFreeURI(uri);
}
}
}
} else {
if ((RAW == '"') || (RAW == '\'')) {
value = xmlParseEntityValue(ctxt, &orig);
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
ctxt->sax->entityDecl(ctxt->userData, name,
XML_INTERNAL_GENERAL_ENTITY,
NULL, NULL, value);
if ((ctxt->myDoc == NULL) ||
(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
if (ctxt->myDoc == NULL) {
ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
}
if (ctxt->myDoc->intSubset == NULL)
ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
BAD_CAST "fake", NULL, NULL);
entityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
NULL, NULL, value);
}
} else {
URI = xmlParseExternalID(ctxt, &literal, 1);
if ((URI == NULL) && (literal == NULL)) {
ctxt->errNo = XML_ERR_VALUE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity value required\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (URI) {
xmlURIPtr uri;
uri = xmlParseURI((const char *)URI);
if (uri == NULL) {
ctxt->errNo = XML_ERR_INVALID_URI;
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Invalid URI: %s\n", URI);
} else {
if (uri->fragment != NULL) {
ctxt->errNo = XML_ERR_URI_FRAGMENT;
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Fragment not allowed: %s\n", URI);
ctxt->wellFormed = 0;
}
xmlFreeURI(uri);
}
}
if ((RAW != '>') && (!IS_BLANK(CUR))) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required before 'NDATA'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
if ((RAW == 'N') && (NXT(1) == 'D') &&
(NXT(2) == 'A') && (NXT(3) == 'T') &&
(NXT(4) == 'A')) {
SKIP(5);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after 'NDATA'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
ndata = xmlParseName(ctxt);
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->unparsedEntityDecl != NULL))
ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
literal, URI, ndata);
} else {
if ((ctxt->sax != NULL) &&
(!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
ctxt->sax->entityDecl(ctxt->userData, name,
XML_EXTERNAL_GENERAL_PARSED_ENTITY,
literal, URI, NULL);
if ((ctxt->replaceEntities != 0) &&
((ctxt->myDoc == NULL) ||
(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
if (ctxt->myDoc == NULL) {
ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
}
if (ctxt->myDoc->intSubset == NULL)
ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
BAD_CAST "fake", NULL, NULL);
entityDecl(ctxt, name,
XML_EXTERNAL_GENERAL_PARSED_ENTITY,
literal, URI, NULL);
}
}
}
}
SKIP_BLANKS;
if (RAW != '>') {
ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseEntityDecl: entity %s not terminated\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity declaration doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
}
if (orig != NULL) {
xmlEntityPtr cur = NULL;
if (isParameter) {
if ((ctxt->sax != NULL) &&
(ctxt->sax->getParameterEntity != NULL))
cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
} else {
if ((ctxt->sax != NULL) &&
(ctxt->sax->getEntity != NULL))
cur = ctxt->sax->getEntity(ctxt->userData, name);
if ((cur == NULL) && (ctxt->userData==ctxt)) {
cur = getEntity(ctxt, name);
}
}
if (cur != NULL) {
if (cur->orig != NULL)
xmlFree(orig);
else
cur->orig = orig;
} else
xmlFree(orig);
}
if (name != NULL) xmlFree(name);
if (value != NULL) xmlFree(value);
if (URI != NULL) xmlFree(URI);
if (literal != NULL) xmlFree(literal);
if (ndata != NULL) xmlFree(ndata);
}
}
int
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
int val;
xmlChar *ret;
*value = NULL;
if ((RAW == '#') && (NXT(1) == 'R') &&
(NXT(2) == 'E') && (NXT(3) == 'Q') &&
(NXT(4) == 'U') && (NXT(5) == 'I') &&
(NXT(6) == 'R') && (NXT(7) == 'E') &&
(NXT(8) == 'D')) {
SKIP(9);
return(XML_ATTRIBUTE_REQUIRED);
}
if ((RAW == '#') && (NXT(1) == 'I') &&
(NXT(2) == 'M') && (NXT(3) == 'P') &&
(NXT(4) == 'L') && (NXT(5) == 'I') &&
(NXT(6) == 'E') && (NXT(7) == 'D')) {
SKIP(8);
return(XML_ATTRIBUTE_IMPLIED);
}
val = XML_ATTRIBUTE_NONE;
if ((RAW == '#') && (NXT(1) == 'F') &&
(NXT(2) == 'I') && (NXT(3) == 'X') &&
(NXT(4) == 'E') && (NXT(5) == 'D')) {
SKIP(6);
val = XML_ATTRIBUTE_FIXED;
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after '#FIXED'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
}
ret = xmlParseAttValue(ctxt);
ctxt->instate = XML_PARSER_DTD;
if (ret == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attribute default value declaration error\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
*value = ret;
return(val);
}
xmlEnumerationPtr
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlEnumerationPtr ret = NULL, last = NULL, cur;
if (RAW != '(') {
ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"'(' required to start 'NOTATION'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
SHRINK;
do {
NEXT;
SKIP_BLANKS;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Name expected in NOTATION declaration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(ret);
}
cur = xmlCreateEnumeration(name);
xmlFree(name);
if (cur == NULL) return(ret);
if (last == NULL) ret = last = cur;
else {
last->next = cur;
last = cur;
}
SKIP_BLANKS;
} while (RAW == '|');
if (RAW != ')') {
ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"')' required to finish NOTATION declaration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if ((last != NULL) && (last != ret))
xmlFreeEnumeration(last);
return(ret);
}
NEXT;
return(ret);
}
xmlEnumerationPtr
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlEnumerationPtr ret = NULL, last = NULL, cur;
if (RAW != '(') {
ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"'(' required to start ATTLIST enumeration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
SHRINK;
do {
NEXT;
SKIP_BLANKS;
name = xmlParseNmtoken(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"NmToken expected in ATTLIST enumeration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(ret);
}
cur = xmlCreateEnumeration(name);
xmlFree(name);
if (cur == NULL) return(ret);
if (last == NULL) ret = last = cur;
else {
last->next = cur;
last = cur;
}
SKIP_BLANKS;
} while (RAW == '|');
if (RAW != ')') {
ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"')' required to finish ATTLIST enumeration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(ret);
}
NEXT;
return(ret);
}
int
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
if ((RAW == 'N') && (NXT(1) == 'O') &&
(NXT(2) == 'T') && (NXT(3) == 'A') &&
(NXT(4) == 'T') && (NXT(5) == 'I') &&
(NXT(6) == 'O') && (NXT(7) == 'N')) {
SKIP(8);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after 'NOTATION'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(0);
}
SKIP_BLANKS;
*tree = xmlParseNotationType(ctxt);
if (*tree == NULL) return(0);
return(XML_ATTRIBUTE_NOTATION);
}
*tree = xmlParseEnumerationType(ctxt);
if (*tree == NULL) return(0);
return(XML_ATTRIBUTE_ENUMERATION);
}
int
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
SHRINK;
if ((RAW == 'C') && (NXT(1) == 'D') &&
(NXT(2) == 'A') && (NXT(3) == 'T') &&
(NXT(4) == 'A')) {
SKIP(5);
return(XML_ATTRIBUTE_CDATA);
} else if ((RAW == 'I') && (NXT(1) == 'D') &&
(NXT(2) == 'R') && (NXT(3) == 'E') &&
(NXT(4) == 'F') && (NXT(5) == 'S')) {
SKIP(6);
return(XML_ATTRIBUTE_IDREFS);
} else if ((RAW == 'I') && (NXT(1) == 'D') &&
(NXT(2) == 'R') && (NXT(3) == 'E') &&
(NXT(4) == 'F')) {
SKIP(5);
return(XML_ATTRIBUTE_IDREF);
} else if ((RAW == 'I') && (NXT(1) == 'D')) {
SKIP(2);
return(XML_ATTRIBUTE_ID);
} else if ((RAW == 'E') && (NXT(1) == 'N') &&
(NXT(2) == 'T') && (NXT(3) == 'I') &&
(NXT(4) == 'T') && (NXT(5) == 'Y')) {
SKIP(6);
return(XML_ATTRIBUTE_ENTITY);
} else if ((RAW == 'E') && (NXT(1) == 'N') &&
(NXT(2) == 'T') && (NXT(3) == 'I') &&
(NXT(4) == 'T') && (NXT(5) == 'I') &&
(NXT(6) == 'E') && (NXT(7) == 'S')) {
SKIP(8);
return(XML_ATTRIBUTE_ENTITIES);
} else if ((RAW == 'N') && (NXT(1) == 'M') &&
(NXT(2) == 'T') && (NXT(3) == 'O') &&
(NXT(4) == 'K') && (NXT(5) == 'E') &&
(NXT(6) == 'N') && (NXT(7) == 'S')) {
SKIP(8);
return(XML_ATTRIBUTE_NMTOKENS);
} else if ((RAW == 'N') && (NXT(1) == 'M') &&
(NXT(2) == 'T') && (NXT(3) == 'O') &&
(NXT(4) == 'K') && (NXT(5) == 'E') &&
(NXT(6) == 'N')) {
SKIP(7);
return(XML_ATTRIBUTE_NMTOKEN);
}
return(xmlParseEnumeratedType(ctxt, tree));
}
void
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
xmlChar *elemName;
xmlChar *attrName;
xmlEnumerationPtr tree;
if ((RAW == '<') && (NXT(1) == '!') &&
(NXT(2) == 'A') && (NXT(3) == 'T') &&
(NXT(4) == 'T') && (NXT(5) == 'L') &&
(NXT(6) == 'I') && (NXT(7) == 'S') &&
(NXT(8) == 'T')) {
xmlParserInputPtr input = ctxt->input;
SKIP(9);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after '<!ATTLIST'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
elemName = xmlParseName(ctxt);
if (elemName == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"ATTLIST: no name for Element\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
SKIP_BLANKS;
GROW;
while (RAW != '>') {
const xmlChar *check = CUR_PTR;
int type;
int def;
xmlChar *defaultValue = NULL;
GROW;
tree = NULL;
attrName = xmlParseName(ctxt);
if (attrName == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"ATTLIST: no name for Attribute\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
}
GROW;
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the attribute name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
break;
}
SKIP_BLANKS;
type = xmlParseAttributeType(ctxt, &tree);
if (type <= 0) {
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
break;
}
GROW;
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the attribute type\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
if (tree != NULL)
xmlFreeEnumeration(tree);
break;
}
SKIP_BLANKS;
def = xmlParseDefaultDecl(ctxt, &defaultValue);
if (def <= 0) {
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
if (tree != NULL)
xmlFreeEnumeration(tree);
break;
}
GROW;
if (RAW != '>') {
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the attribute default value\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
if (tree != NULL)
xmlFreeEnumeration(tree);
break;
}
SKIP_BLANKS;
}
if (check == CUR_PTR) {
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseAttributeListDecl: detected internal error\n");
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
if (tree != NULL)
xmlFreeEnumeration(tree);
break;
}
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->attributeDecl != NULL))
ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
type, def, defaultValue, tree);
if (attrName != NULL)
xmlFree(attrName);
if (defaultValue != NULL)
xmlFree(defaultValue);
GROW;
}
if (RAW == '>') {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attribute list declaration doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
}
xmlFree(elemName);
}
}
xmlElementContentPtr
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, xmlParserInputPtr inputchk) {
xmlElementContentPtr ret = NULL, cur = NULL, n;
xmlChar *elem = NULL;
GROW;
if ((RAW == '#') && (NXT(1) == 'P') &&
(NXT(2) == 'C') && (NXT(3) == 'D') &&
(NXT(4) == 'A') && (NXT(5) == 'T') &&
(NXT(6) == 'A')) {
SKIP(7);
SKIP_BLANKS;
SHRINK;
if (RAW == ')') {
if ((ctxt->validate) && (ctxt->input != inputchk)) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if (ctxt->vctxt.error != NULL)
ctxt->vctxt.error(ctxt->vctxt.userData,
"Element content declaration doesn't start and stop in the same entity\n");
ctxt->valid = 0;
}
NEXT;
ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
if (RAW == '*') {
ret->ocur = XML_ELEMENT_CONTENT_MULT;
NEXT;
}
return(ret);
}
if ((RAW == '(') || (RAW == '|')) {
ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
if (ret == NULL) return(NULL);
}
while (RAW == '|') {
NEXT;
if (elem == NULL) {
ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
if (ret == NULL) return(NULL);
ret->c1 = cur;
if (cur != NULL)
cur->parent = ret;
cur = ret;
} else {
n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
if (n == NULL) return(NULL);
n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
if (n->c1 != NULL)
n->c1->parent = n;
cur->c2 = n;
if (n != NULL)
n->parent = cur;
cur = n;
xmlFree(elem);
}
SKIP_BLANKS;
elem = xmlParseName(ctxt);
if (elem == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementMixedContentDecl : Name expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
xmlFreeElementContent(cur);
return(NULL);
}
SKIP_BLANKS;
GROW;
}
if ((RAW == ')') && (NXT(1) == '*')) {
if (elem != NULL) {
cur->c2 = xmlNewElementContent(elem,
XML_ELEMENT_CONTENT_ELEMENT);
if (cur->c2 != NULL)
cur->c2->parent = cur;
xmlFree(elem);
}
ret->ocur = XML_ELEMENT_CONTENT_MULT;
if ((ctxt->validate) && (ctxt->input != inputchk)) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if (ctxt->vctxt.error != NULL)
ctxt->vctxt.error(ctxt->vctxt.userData,
"Element content declaration doesn't start and stop in the same entity\n");
ctxt->valid = 0;
}
SKIP(2);
} else {
if (elem != NULL) xmlFree(elem);
xmlFreeElementContent(ret);
ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
} else {
ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
return(ret);
}
xmlElementContentPtr
xmlParseElementChildrenContentDecl
(xmlParserCtxtPtr ctxt, xmlParserInputPtr inputchk) {
xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
xmlChar *elem;
xmlChar type = 0;
SKIP_BLANKS;
GROW;
if (RAW == '(') {
xmlParserInputPtr input = ctxt->input;
NEXT;
SKIP_BLANKS;
cur = ret = xmlParseElementChildrenContentDecl(ctxt, input);
SKIP_BLANKS;
GROW;
} else {
elem = xmlParseName(ctxt);
if (elem == NULL) {
ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementChildrenContentDecl : Name or '(' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
GROW;
if (RAW == '?') {
cur->ocur = XML_ELEMENT_CONTENT_OPT;
NEXT;
} else if (RAW == '*') {
cur->ocur = XML_ELEMENT_CONTENT_MULT;
NEXT;
} else if (RAW == '+') {
cur->ocur = XML_ELEMENT_CONTENT_PLUS;
NEXT;
} else {
cur->ocur = XML_ELEMENT_CONTENT_ONCE;
}
xmlFree(elem);
GROW;
}
SKIP_BLANKS;
SHRINK;
while (RAW != ')') {
if (RAW == ',') {
if (type == 0) type = CUR;
else if (type != CUR) {
ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementChildrenContentDecl : '%c' expected\n",
type);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if ((last != NULL) && (last != ret))
xmlFreeElementContent(last);
if (ret != NULL)
xmlFreeElementContent(ret);
return(NULL);
}
NEXT;
op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
if (op == NULL) {
if ((last != NULL) && (last != ret))
xmlFreeElementContent(last);
xmlFreeElementContent(ret);
return(NULL);
}
if (last == NULL) {
op->c1 = ret;
if (ret != NULL)
ret->parent = op;
ret = cur = op;
} else {
cur->c2 = op;
if (op != NULL)
op->parent = cur;
op->c1 = last;
if (last != NULL)
last->parent = op;
cur =op;
last = NULL;
}
} else if (RAW == '|') {
if (type == 0) type = CUR;
else if (type != CUR) {
ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementChildrenContentDecl : '%c' expected\n",
type);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if ((last != NULL) && (last != ret))
xmlFreeElementContent(last);
if (ret != NULL)
xmlFreeElementContent(ret);
return(NULL);
}
NEXT;
op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
if (op == NULL) {
if ((last != NULL) && (last != ret))
xmlFreeElementContent(last);
if (ret != NULL)
xmlFreeElementContent(ret);
return(NULL);
}
if (last == NULL) {
op->c1 = ret;
if (ret != NULL)
ret->parent = op;
ret = cur = op;
} else {
cur->c2 = op;
if (op != NULL)
op->parent = cur;
op->c1 = last;
if (last != NULL)
last->parent = op;
cur =op;
last = NULL;
}
} else {
ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if (ret != NULL)
xmlFreeElementContent(ret);
return(NULL);
}
GROW;
SKIP_BLANKS;
GROW;
if (RAW == '(') {
xmlParserInputPtr input = ctxt->input;
NEXT;
SKIP_BLANKS;
last = xmlParseElementChildrenContentDecl(ctxt, input);
SKIP_BLANKS;
} else {
elem = xmlParseName(ctxt);
if (elem == NULL) {
ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementChildrenContentDecl : Name or '(' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if (ret != NULL)
xmlFreeElementContent(ret);
return(NULL);
}
last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
xmlFree(elem);
if (RAW == '?') {
last->ocur = XML_ELEMENT_CONTENT_OPT;
NEXT;
} else if (RAW == '*') {
last->ocur = XML_ELEMENT_CONTENT_MULT;
NEXT;
} else if (RAW == '+') {
last->ocur = XML_ELEMENT_CONTENT_PLUS;
NEXT;
} else {
last->ocur = XML_ELEMENT_CONTENT_ONCE;
}
}
SKIP_BLANKS;
GROW;
}
if ((cur != NULL) && (last != NULL)) {
cur->c2 = last;
if (last != NULL)
last->parent = cur;
}
if ((ctxt->validate) && (ctxt->input != inputchk)) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if (ctxt->vctxt.error != NULL)
ctxt->vctxt.error(ctxt->vctxt.userData,
"Element content declaration doesn't start and stop in the same entity\n");
ctxt->valid = 0;
}
NEXT;
if (RAW == '?') {
if (ret != NULL)
ret->ocur = XML_ELEMENT_CONTENT_OPT;
NEXT;
} else if (RAW == '*') {
if (ret != NULL) {
ret->ocur = XML_ELEMENT_CONTENT_MULT;
cur = ret;
while (cur->type == XML_ELEMENT_CONTENT_OR) {
if ((cur->c1 != NULL) &&
((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
(cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
if ((cur->c2 != NULL) &&
((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
(cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
cur = cur->c2;
}
}
NEXT;
} else if (RAW == '+') {
if (ret != NULL) {
int found = 0;
ret->ocur = XML_ELEMENT_CONTENT_PLUS;
while (cur->type == XML_ELEMENT_CONTENT_OR) {
if ((cur->c1 != NULL) &&
((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
(cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
found = 1;
}
if ((cur->c2 != NULL) &&
((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
(cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
found = 1;
}
cur = cur->c2;
}
if (found)
ret->ocur = XML_ELEMENT_CONTENT_MULT;
}
NEXT;
}
return(ret);
}
int
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
xmlElementContentPtr *result) {
xmlElementContentPtr tree = NULL;
xmlParserInputPtr input = ctxt->input;
int res;
*result = NULL;
if (RAW != '(') {
ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementContentDecl : %s '(' expected\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(-1);
}
NEXT;
GROW;
SKIP_BLANKS;
if ((RAW == '#') && (NXT(1) == 'P') &&
(NXT(2) == 'C') && (NXT(3) == 'D') &&
(NXT(4) == 'A') && (NXT(5) == 'T') &&
(NXT(6) == 'A')) {
tree = xmlParseElementMixedContentDecl(ctxt, input);
res = XML_ELEMENT_TYPE_MIXED;
} else {
tree = xmlParseElementChildrenContentDecl(ctxt, input);
res = XML_ELEMENT_TYPE_ELEMENT;
}
SKIP_BLANKS;
*result = tree;
return(res);
}
int
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
xmlChar *name;
int ret = -1;
xmlElementContentPtr content = NULL;
GROW;
if ((RAW == '<') && (NXT(1) == '!') &&
(NXT(2) == 'E') && (NXT(3) == 'L') &&
(NXT(4) == 'E') && (NXT(5) == 'M') &&
(NXT(6) == 'E') && (NXT(7) == 'N') &&
(NXT(8) == 'T')) {
xmlParserInputPtr input = ctxt->input;
SKIP(9);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after 'ELEMENT'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementDecl: no name for Element\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(-1);
}
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space required after the element name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
if ((RAW == 'E') && (NXT(1) == 'M') &&
(NXT(2) == 'P') && (NXT(3) == 'T') &&
(NXT(4) == 'Y')) {
SKIP(5);
ret = XML_ELEMENT_TYPE_EMPTY;
} else if ((RAW == 'A') && (NXT(1) == 'N') &&
(NXT(2) == 'Y')) {
SKIP(3);
ret = XML_ELEMENT_TYPE_ANY;
} else if (RAW == '(') {
ret = xmlParseElementContentDecl(ctxt, name, &content);
} else {
if ((RAW == '%') && (ctxt->external == 0) &&
(ctxt->inputNr == 1)) {
ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"PEReference: forbidden within markup decl in internal subset\n");
} else {
ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
}
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
if (name != NULL) xmlFree(name);
return(-1);
}
SKIP_BLANKS;
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
SKIP_BLANKS;
if (RAW != '>') {
ctxt->errNo = XML_ERR_GT_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseElementDecl: expected '>' at the end\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (input != ctxt->input) {
ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Element declaration doesn't start and stop in the same entity\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->elementDecl != NULL))
ctxt->sax->elementDecl(ctxt->userData, name, ret,
content);
}
if (content != NULL) {
xmlFreeElementContent(content);
}
if (name != NULL) {
xmlFree(name);
}
}
return(ret);
}
static void
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
SKIP(3);
SKIP_BLANKS;
if ((RAW == 'I') && (NXT(1) == 'N') && (NXT(2) == 'C') &&
(NXT(3) == 'L') && (NXT(4) == 'U') && (NXT(5) == 'D') &&
(NXT(6) == 'E')) {
SKIP(7);
SKIP_BLANKS;
if (RAW != '[') {
ctxt->errNo = XML_ERR_CONDSEC_INVALID;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML conditional section '[' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
NEXT;
}
if (xmlParserDebugEntities) {
if ((ctxt->input != NULL) && (ctxt->input->filename))
xmlGenericError(xmlGenericErrorContext,
"%s(%d): ", ctxt->input->filename,
ctxt->input->line);
xmlGenericError(xmlGenericErrorContext,
"Entering INCLUDE Conditional Section\n");
}
while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
(NXT(2) != '>'))) {
const xmlChar *check = CUR_PTR;
int cons = ctxt->input->consumed;
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
} else if (IS_BLANK(CUR)) {
NEXT;
} else if (RAW == '%') {
xmlParsePEReference(ctxt);
} else
xmlParseMarkupDecl(ctxt);
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Content error in the external subset\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
}
}
if (xmlParserDebugEntities) {
if ((ctxt->input != NULL) && (ctxt->input->filename))
xmlGenericError(xmlGenericErrorContext,
"%s(%d): ", ctxt->input->filename,
ctxt->input->line);
xmlGenericError(xmlGenericErrorContext,
"Leaving INCLUDE Conditional Section\n");
}
} else if ((RAW == 'I') && (NXT(1) == 'G') && (NXT(2) == 'N') &&
(NXT(3) == 'O') && (NXT(4) == 'R') && (NXT(5) == 'E')) {
int state;
int instate;
int depth = 0;
SKIP(6);
SKIP_BLANKS;
if (RAW != '[') {
ctxt->errNo = XML_ERR_CONDSEC_INVALID;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML conditional section '[' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
NEXT;
}
if (xmlParserDebugEntities) {
if ((ctxt->input != NULL) && (ctxt->input->filename))
xmlGenericError(xmlGenericErrorContext,
"%s(%d): ", ctxt->input->filename,
ctxt->input->line);
xmlGenericError(xmlGenericErrorContext,
"Entering IGNORE Conditional Section\n");
}
state = ctxt->disableSAX;
instate = ctxt->instate;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_IGNORE;
while ((depth >= 0) && (RAW != 0)) {
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
depth++;
SKIP(3);
continue;
}
if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
if (--depth >= 0) SKIP(3);
continue;
}
NEXT;
continue;
}
ctxt->disableSAX = state;
ctxt->instate = instate;
if (xmlParserDebugEntities) {
if ((ctxt->input != NULL) && (ctxt->input->filename))
xmlGenericError(xmlGenericErrorContext,
"%s(%d): ", ctxt->input->filename,
ctxt->input->line);
xmlGenericError(xmlGenericErrorContext,
"Leaving IGNORE Conditional Section\n");
}
} else {
ctxt->errNo = XML_ERR_CONDSEC_INVALID;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML conditional section INCLUDE or IGNORE keyword expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (RAW == 0)
SHRINK;
if (RAW == 0) {
ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML conditional section not closed\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
SKIP(3);
}
}
void
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
GROW;
xmlParseElementDecl(ctxt);
xmlParseAttributeListDecl(ctxt);
xmlParseEntityDecl(ctxt);
xmlParseNotationDecl(ctxt);
xmlParsePI(ctxt);
xmlParseComment(ctxt);
if ((ctxt->external == 0) && (ctxt->inputNr == 1))
xmlParsePEReference(ctxt);
if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
}
}
ctxt->instate = XML_PARSER_DTD;
}
void
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
xmlChar *version;
if ((RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
SKIP(5);
} else {
ctxt->errNo = XML_ERR_XMLDECL_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Text declaration '<?xml' required\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Space needed after '<?xml'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
version = xmlParseVersionInfo(ctxt);
if (version == NULL)
version = xmlCharStrdup(XML_DEFAULT_VERSION);
else {
if (!IS_BLANK(CUR)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Space needed here\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
ctxt->input->version = version;
xmlParseEncodingDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
return;
}
SKIP_BLANKS;
if ((RAW == '?') && (NXT(1) == '>')) {
SKIP(2);
} else if (RAW == '>') {
ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML declaration must end-up with '?>'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
NEXT;
} else {
ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"parsing XML declaration: '?>' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
MOVETO_ENDTAG(CUR_PTR);
NEXT;
}
}
void
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
const xmlChar *SystemID) {
GROW;
if ((RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l')) {
xmlParseTextDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
ctxt->instate = XML_PARSER_EOF;
return;
}
}
if (ctxt->myDoc == NULL) {
ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
}
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
ctxt->instate = XML_PARSER_DTD;
ctxt->external = 1;
while (((RAW == '<') && (NXT(1) == '?')) ||
((RAW == '<') && (NXT(1) == '!')) ||
(RAW == '%') || IS_BLANK(CUR)) {
const xmlChar *check = CUR_PTR;
int cons = ctxt->input->consumed;
GROW;
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
} else if (IS_BLANK(CUR)) {
NEXT;
} else if (RAW == '%') {
xmlParsePEReference(ctxt);
} else
xmlParseMarkupDecl(ctxt);
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Content error in the external subset\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
}
}
if (RAW != 0) {
ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Extra content at the end of the document\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
void
xmlParseReference(xmlParserCtxtPtr ctxt) {
xmlEntityPtr ent;
xmlChar *val;
if (RAW != '&') return;
if (NXT(1) == '#') {
int i = 0;
xmlChar out[10];
int hex = NXT(2);
int value = xmlParseCharRef(ctxt);
if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
if (value <= 0xFF) {
out[0] = value;
out[1] = 0;
if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->characters(ctxt->userData, out, 1);
} else {
if ((hex == 'x') || (hex == 'X'))
snprintf((char *)out, sizeof(out), "#x%X", value);
else
snprintf((char *)out, sizeof(out), "#%d", value);
if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->reference(ctxt->userData, out);
}
} else {
COPY_BUF(0 ,out, i, value);
out[i] = 0;
if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->characters(ctxt->userData, out, i);
}
} else {
ent = xmlParseEntityRef(ctxt);
if (ent == NULL) return;
if (!ctxt->wellFormed)
return;
if ((ent->name != NULL) &&
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
xmlNodePtr list = NULL;
int ret;
if (ent->children == NULL) {
xmlChar *value;
value = ent->content;
if ((value != NULL) &&
(value[1] == 0) && (value[0] == '<') &&
(xmlStrEqual(ent->name, BAD_CAST "lt"))) {
list = xmlNewDocText(ctxt->myDoc, value);
if (list != NULL) {
if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) &&
(ent->children == NULL)) {
ent->children = list;
ent->last = list;
ent->owner = 1;
list->parent = (xmlNodePtr) ent;
} else {
xmlFreeNodeList(list);
}
} else if (list != NULL) {
xmlFreeNodeList(list);
}
} else {
void *user_data;
if (ctxt->userData == ctxt)
user_data = NULL;
else
user_data = ctxt->userData;
if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
ctxt->depth++;
ret = xmlParseBalancedChunkMemoryInternal(ctxt,
value, user_data, &list);
ctxt->depth--;
} else if (ent->etype ==
XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
ctxt->depth++;
ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
ctxt->sax, user_data, ctxt->depth,
ent->URI, ent->ExternalID, &list);
ctxt->depth--;
} else {
ret = -1;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Internal: invalid entity type\n");
}
if (ret == XML_ERR_ENTITY_LOOP) {
ctxt->errNo = XML_ERR_ENTITY_LOOP;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Detected entity reference loop\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
} else if ((ret == 0) && (list != NULL)) {
if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
(ent->children == NULL)) {
ent->children = list;
if (ctxt->replaceEntities) {
if ((list->type == XML_TEXT_NODE) &&
(list->next == NULL)) {
list->parent = (xmlNodePtr) ent;
list = NULL;
ent->owner = 1;
} else {
ent->owner = 0;
while (list != NULL) {
list->parent = (xmlNodePtr) ctxt->node;
list->doc = ctxt->myDoc;
if (list->next == NULL)
ent->last = list;
list = list->next;
}
list = ent->children;
if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
xmlAddEntityReference(ent, list, NULL);
}
} else {
ent->owner = 1;
while (list != NULL) {
list->parent = (xmlNodePtr) ent;
if (list->next == NULL)
ent->last = list;
list = list->next;
}
}
} else {
xmlFreeNodeList(list);
list = NULL;
}
} else if (ret > 0) {
ctxt->errNo = ret;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity value required\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (list != NULL) {
xmlFreeNodeList(list);
list = NULL;
}
}
}
if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
(ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
ctxt->sax->reference(ctxt->userData, ent->name);
return;
} else if (ctxt->replaceEntities) {
if ((ctxt->node != NULL) && (ent->children != NULL)) {
if (list == NULL) {
xmlNodePtr new = NULL, cur, firstChild = NULL;
cur = ent->children;
while (cur != NULL) {
new = xmlCopyNode(cur, 1);
if (new != NULL) {
new->_private = cur->_private;
if (firstChild == NULL){
firstChild = new;
}
xmlAddChild(ctxt->node, new);
}
if (cur == ent->last)
break;
cur = cur->next;
}
if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
xmlAddEntityReference(ent, firstChild, new);
} else {
if (ent->children->type == XML_TEXT_NODE)
ent->children->name = xmlStrdup(BAD_CAST "nbktext");
if ((ent->last != ent->children) &&
(ent->last->type == XML_TEXT_NODE))
ent->last->name = xmlStrdup(BAD_CAST "nbktext");
xmlAddChildList(ctxt->node, ent->children);
}
ctxt->nodemem = 0;
ctxt->nodelen = 0;
return;
} else {
xmlParserInputPtr input;
input = xmlNewEntityInputStream(ctxt, ent);
xmlPushInput(ctxt, input);
if ((ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) &&
(RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseTextDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
ctxt->instate = XML_PARSER_EOF;
return;
}
if (input->standalone == 1) {
ctxt->errNo = XML_ERR_EXT_ENTITY_STANDALONE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"external parsed entities cannot be standalone\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
return;
}
}
} else {
val = ent->content;
if (val == NULL) return;
if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
}
}
}
xmlEntityPtr
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlEntityPtr ent = NULL;
GROW;
if (RAW == '&') {
NEXT;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseEntityRef: no name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (RAW == ';') {
NEXT;
if (ctxt->sax != NULL) {
if (ctxt->sax->getEntity != NULL)
ent = ctxt->sax->getEntity(ctxt->userData, name);
if (ent == NULL)
ent = xmlGetPredefinedEntity(name);
if ((ent == NULL) && (ctxt->userData==ctxt)) {
ent = getEntity(ctxt, name);
}
}
if (ent == NULL) {
if ((ctxt->standalone == 1) ||
((ctxt->hasExternalSubset == 0) &&
(ctxt->hasPErefs == 0))) {
ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity '%s' not defined\n", name);
ctxt->wellFormed = 0;
ctxt->valid = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity '%s' not defined\n", name);
ctxt->valid = 0;
}
}
else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity reference to unparsed entity %s\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attribute references external entity '%s'\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
(ent != NULL) &&
(!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
(ent->content != NULL) &&
(xmlStrchr(ent->content, '<'))) {
ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"'<' in entity '%s' is not allowed in attributes values\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
else {
switch (ent->etype) {
case XML_INTERNAL_PARAMETER_ENTITY:
case XML_EXTERNAL_PARAMETER_ENTITY:
ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attempt to reference the parameter entity '%s'\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
default:
break;
}
}
} else {
ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseEntityRef: expecting ';'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlFree(name);
}
}
return(ent);
}
xmlEntityPtr
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
xmlChar *name;
const xmlChar *ptr;
xmlChar cur;
xmlEntityPtr ent = NULL;
if ((str == NULL) || (*str == NULL))
return(NULL);
ptr = *str;
cur = *ptr;
if (cur == '&') {
ptr++;
cur = *ptr;
name = xmlParseStringName(ctxt, &ptr);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringEntityRef: no name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (*ptr == ';') {
ptr++;
if (ctxt->sax != NULL) {
if (ctxt->sax->getEntity != NULL)
ent = ctxt->sax->getEntity(ctxt->userData, name);
if (ent == NULL)
ent = xmlGetPredefinedEntity(name);
if ((ent == NULL) && (ctxt->userData==ctxt)) {
ent = getEntity(ctxt, name);
}
}
if (ent == NULL) {
if ((ctxt->standalone == 1) ||
((ctxt->hasExternalSubset == 0) &&
(ctxt->hasPErefs == 0))) {
ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity '%s' not defined\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"Entity '%s' not defined\n", name);
}
}
else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity reference to unparsed entity %s\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attribute references external entity '%s'\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
(ent != NULL) &&
(!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
(ent->content != NULL) &&
(xmlStrchr(ent->content, '<'))) {
ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"'<' in entity '%s' is not allowed in attributes values\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
else {
switch (ent->etype) {
case XML_INTERNAL_PARAMETER_ENTITY:
case XML_EXTERNAL_PARAMETER_ENTITY:
ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attempt to reference the parameter entity '%s'\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
default:
break;
}
}
} else {
ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringEntityRef: expecting ';'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlFree(name);
}
}
*str = ptr;
return(ent);
}
void
xmlParsePEReference(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlEntityPtr entity = NULL;
xmlParserInputPtr input;
if (RAW == '%') {
NEXT;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParsePEReference: no name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (RAW == ';') {
NEXT;
if ((ctxt->sax != NULL) &&
(ctxt->sax->getParameterEntity != NULL))
entity = ctxt->sax->getParameterEntity(ctxt->userData,
name);
if (entity == NULL) {
if ((ctxt->standalone == 1) ||
((ctxt->hasExternalSubset == 0) &&
(ctxt->hasPErefs == 0))) {
ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
if ((!ctxt->disableSAX) &&
(ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"PEReference: %%%s; not found\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if ((!ctxt->disableSAX) &&
(ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"PEReference: %%%s; not found\n", name);
ctxt->valid = 0;
}
} else {
if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
(entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"Internal: %%%s; is not a parameter entity\n", name);
} else if (ctxt->input->free != deallocblankswrapper) {
input = xmlNewBlanksWrapperInputStream(ctxt, entity);
xmlPushInput(ctxt, input);
} else {
input = xmlNewEntityInputStream(ctxt, entity);
xmlPushInput(ctxt, input);
if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
(RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseTextDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
ctxt->instate = XML_PARSER_EOF;
xmlFree(name);
return;
}
}
}
}
ctxt->hasPErefs = 1;
} else {
ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParsePEReference: expecting ';'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlFree(name);
}
}
}
xmlEntityPtr
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
const xmlChar *ptr;
xmlChar cur;
xmlChar *name;
xmlEntityPtr entity = NULL;
if ((str == NULL) || (*str == NULL)) return(NULL);
ptr = *str;
cur = *ptr;
if (cur == '%') {
ptr++;
cur = *ptr;
name = xmlParseStringName(ctxt, &ptr);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringPEReference: no name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
cur = *ptr;
if (cur == ';') {
ptr++;
cur = *ptr;
if ((ctxt->sax != NULL) &&
(ctxt->sax->getParameterEntity != NULL))
entity = ctxt->sax->getParameterEntity(ctxt->userData,
name);
if (entity == NULL) {
if ((ctxt->standalone == 1) ||
((ctxt->hasExternalSubset == 0) &&
(ctxt->hasPErefs == 0))) {
ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"PEReference: %%%s; not found\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"PEReference: %%%s; not found\n", name);
ctxt->valid = 0;
}
} else {
if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
(entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"Internal: %%%s; is not a parameter entity\n", name);
}
}
ctxt->hasPErefs = 1;
} else {
ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStringPEReference: expecting ';'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlFree(name);
}
}
*str = ptr;
return(entity);
}
void
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
xmlChar *name = NULL;
xmlChar *ExternalID = NULL;
xmlChar *URI = NULL;
SKIP(9);
SKIP_BLANKS;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseDocTypeDecl : no DOCTYPE name !\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
ctxt->intSubName = name;
SKIP_BLANKS;
URI = xmlParseExternalID(ctxt, &ExternalID, 1);
if ((URI != NULL) || (ExternalID != NULL)) {
ctxt->hasExternalSubset = 1;
}
ctxt->extSubURI = URI;
ctxt->extSubSystem = ExternalID;
SKIP_BLANKS;
if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
if (RAW == '[')
return;
if (RAW != '>') {
ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "DOCTYPE improperly terminated\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
}
static void
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
if (RAW == '[') {
ctxt->instate = XML_PARSER_DTD;
NEXT;
while (RAW != ']') {
const xmlChar *check = CUR_PTR;
int cons = ctxt->input->consumed;
SKIP_BLANKS;
xmlParseMarkupDecl(ctxt);
xmlParsePEReference(ctxt);
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseInternalSubset: error detected in Markup declaration\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
}
}
if (RAW == ']') {
NEXT;
SKIP_BLANKS;
}
}
if (RAW != '>') {
ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "DOCTYPE improperly terminated\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
NEXT;
}
xmlChar *
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
xmlChar *name, *val;
*value = NULL;
GROW;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
SKIP_BLANKS;
if (RAW == '=') {
NEXT;
SKIP_BLANKS;
val = xmlParseAttValue(ctxt);
ctxt->instate = XML_PARSER_CONTENT;
} else {
ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Specification mandate value for attribute %s\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
xmlFree(name);
return(NULL);
}
if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
if (!xmlCheckLanguageID(val)) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"Malformed value for xml:lang : %s\n", val);
}
}
if (xmlStrEqual(name, BAD_CAST "xml:space")) {
if (xmlStrEqual(val, BAD_CAST "default"))
*(ctxt->space) = 0;
else if (xmlStrEqual(val, BAD_CAST "preserve"))
*(ctxt->space) = 1;
else {
ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Invalid value for xml:space : \"%s\", \"default\" or \"preserve\" expected\n",
val);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
*value = val;
return(name);
}
xmlChar *
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlChar *attname;
xmlChar *attvalue;
const xmlChar **atts = NULL;
int nbatts = 0;
int maxatts = 0;
int i;
if (RAW != '<') return(NULL);
NEXT1;
name = xmlParseName(ctxt);
if (name == NULL) {
ctxt->errNo = XML_ERR_NAME_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStartTag: invalid element name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
SKIP_BLANKS;
GROW;
while ((RAW != '>') &&
((RAW != '/') || (NXT(1) != '>')) &&
(IS_CHAR(RAW))) {
const xmlChar *q = CUR_PTR;
int cons = ctxt->input->consumed;
attname = xmlParseAttribute(ctxt, &attvalue);
if ((attname != NULL) && (attvalue != NULL)) {
for (i = 0; i < nbatts;i += 2) {
if (xmlStrEqual(atts[i], attname)) {
ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Attribute %s redefined\n",
attname);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
xmlFree(attname);
xmlFree(attvalue);
goto failed;
}
}
if (atts == NULL) {
maxatts = 10;
atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
if (atts == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %ld byte failed\n",
maxatts * (long)sizeof(xmlChar *));
return(NULL);
}
} else if (nbatts + 4 > maxatts) {
maxatts *= 2;
atts = (const xmlChar **) xmlRealloc((void *) atts,
maxatts * sizeof(xmlChar *));
if (atts == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %ld byte failed\n",
maxatts * (long)sizeof(xmlChar *));
return(NULL);
}
}
atts[nbatts++] = attname;
atts[nbatts++] = attvalue;
atts[nbatts] = NULL;
atts[nbatts + 1] = NULL;
} else {
if (attname != NULL)
xmlFree(attname);
if (attvalue != NULL)
xmlFree(attvalue);
}
failed:
GROW
if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
break;
if (!IS_BLANK(RAW)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"attributes construct error\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
(attname == NULL) && (attvalue == NULL)) {
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseStartTag: problem parsing attributes\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
}
GROW;
}
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->startElement(ctxt->userData, name, atts);
if (atts != NULL) {
for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
xmlFree((void *) atts);
}
return(name);
}
void
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlChar *oldname;
GROW;
if ((RAW != '<') || (NXT(1) != '/')) {
ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return;
}
SKIP(2);
name = xmlParseNameAndCompare(ctxt,ctxt->name);
GROW;
SKIP_BLANKS;
if ((!IS_CHAR(RAW)) || (RAW != '>')) {
ctxt->errNo = XML_ERR_GT_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT1;
if (name != (xmlChar*)1) {
ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
if (name != NULL) {
ctxt->sax->error(ctxt->userData,
"Opening and ending tag mismatch: %s and %s\n",
ctxt->name, name);
} else {
ctxt->sax->error(ctxt->userData,
"Ending tag error for: %s\n", ctxt->name);
}
}
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
#if 0
else {
if ((ctxt->nameNr > 2) &&
(xmlStrEqual(ctxt->nameTab[ctxt->nameNr -2], name))) {
namePop(ctxt);
spacePop(ctxt);
}
}
#endif
if (name != NULL)
xmlFree(name);
}
if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->endElement(ctxt->userData, ctxt->name);
oldname = namePop(ctxt);
spacePop(ctxt);
if (oldname != NULL) {
#ifdef DEBUG_STACK
xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
#endif
xmlFree(oldname);
}
return;
}
void
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = XML_PARSER_BUFFER_SIZE;
int r, rl;
int s, sl;
int cur, l;
int count = 0;
if ((NXT(0) == '<') && (NXT(1) == '!') &&
(NXT(2) == '[') && (NXT(3) == 'C') &&
(NXT(4) == 'D') && (NXT(5) == 'A') &&
(NXT(6) == 'T') && (NXT(7) == 'A') &&
(NXT(8) == '[')) {
SKIP(9);
} else
return;
ctxt->instate = XML_PARSER_CDATA_SECTION;
r = CUR_CHAR(rl);
if (!IS_CHAR(r)) {
ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"CData section not finished\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_CONTENT;
return;
}
NEXTL(rl);
s = CUR_CHAR(sl);
if (!IS_CHAR(s)) {
ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"CData section not finished\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_CONTENT;
return;
}
NEXTL(sl);
cur = CUR_CHAR(l);
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
return;
}
while (IS_CHAR(cur) &&
((r != ']') || (s != ']') || (cur != '>'))) {
if (len + 5 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
return;
}
}
COPY_BUF(rl,buf,len,r);
r = s;
rl = sl;
s = cur;
sl = l;
count++;
if (count > 50) {
GROW;
count = 0;
}
NEXTL(l);
cur = CUR_CHAR(l);
}
buf[len] = 0;
ctxt->instate = XML_PARSER_CONTENT;
if (cur != '>') {
ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"CData section not finished\n%.50s\n", buf);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
xmlFree(buf);
return;
}
NEXTL(l);
if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
if (ctxt->sax->cdataBlock != NULL)
ctxt->sax->cdataBlock(ctxt->userData, buf, len);
else if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData, buf, len);
}
xmlFree(buf);
}
void
xmlParseContent(xmlParserCtxtPtr ctxt) {
GROW;
while ((RAW != 0) &&
((RAW != '<') || (NXT(1) != '/'))) {
const xmlChar *test = CUR_PTR;
int cons = ctxt->input->consumed;
const xmlChar *cur = ctxt->input->cur;
if ((*cur == '<') && (cur[1] == '?')) {
xmlParsePI(ctxt);
}
else if ((*cur == '<') && (NXT(1) == '!') &&
(NXT(2) == '[') && (NXT(3) == 'C') &&
(NXT(4) == 'D') && (NXT(5) == 'A') &&
(NXT(6) == 'T') && (NXT(7) == 'A') &&
(NXT(8) == '[')) {
xmlParseCDSect(ctxt);
}
else if ((*cur == '<') && (NXT(1) == '!') &&
(NXT(2) == '-') && (NXT(3) == '-')) {
xmlParseComment(ctxt);
ctxt->instate = XML_PARSER_CONTENT;
}
else if (*cur == '<') {
xmlParseElement(ctxt);
}
else if (*cur == '&') {
xmlParseReference(ctxt);
}
else {
xmlParseCharData(ctxt, 0);
}
GROW;
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
SHRINK;
if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"detected an error in element content\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_EOF;
break;
}
}
}
void
xmlParseElement(xmlParserCtxtPtr ctxt) {
xmlChar *name;
xmlChar *oldname;
xmlParserNodeInfo node_info;
xmlNodePtr ret;
if (ctxt->record_info) {
node_info.begin_pos = ctxt->input->consumed +
(CUR_PTR - ctxt->input->base);
node_info.begin_line = ctxt->input->line;
}
if (ctxt->spaceNr == 0)
spacePush(ctxt, -1);
else
spacePush(ctxt, *ctxt->space);
name = xmlParseStartTag(ctxt);
if (name == NULL) {
spacePop(ctxt);
return;
}
namePush(ctxt, name);
ret = ctxt->node;
if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
ctxt->node && (ctxt->node == ctxt->myDoc->children))
ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
if ((RAW == '/') && (NXT(1) == '>')) {
SKIP(2);
if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->endElement(ctxt->userData, name);
oldname = namePop(ctxt);
spacePop(ctxt);
if (oldname != NULL) {
#ifdef DEBUG_STACK
xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
#endif
xmlFree(oldname);
}
if ( ret != NULL && ctxt->record_info ) {
node_info.end_pos = ctxt->input->consumed +
(CUR_PTR - ctxt->input->base);
node_info.end_line = ctxt->input->line;
node_info.node = ret;
xmlParserAddNodeInfo(ctxt, &node_info);
}
return;
}
if (RAW == '>') {
NEXT1;
} else {
ctxt->errNo = XML_ERR_GT_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Couldn't find end of Start Tag %s\n",
name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
nodePop(ctxt);
oldname = namePop(ctxt);
spacePop(ctxt);
if (oldname != NULL) {
#ifdef DEBUG_STACK
xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
#endif
xmlFree(oldname);
}
if ( ret != NULL && ctxt->record_info ) {
node_info.end_pos = ctxt->input->consumed +
(CUR_PTR - ctxt->input->base);
node_info.end_line = ctxt->input->line;
node_info.node = ret;
xmlParserAddNodeInfo(ctxt, &node_info);
}
return;
}
xmlParseContent(ctxt);
if (!IS_CHAR(RAW)) {
ctxt->errNo = XML_ERR_TAG_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Premature end of data in tag %s\n", name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
nodePop(ctxt);
oldname = namePop(ctxt);
spacePop(ctxt);
if (oldname != NULL) {
#ifdef DEBUG_STACK
xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
#endif
xmlFree(oldname);
}
return;
}
xmlParseEndTag(ctxt);
if ( ret != NULL && ctxt->record_info ) {
node_info.end_pos = ctxt->input->consumed +
(CUR_PTR - ctxt->input->base);
node_info.end_line = ctxt->input->line;
node_info.node = ret;
xmlParserAddNodeInfo(ctxt, &node_info);
}
}
xmlChar *
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = 10;
xmlChar cur;
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
return(NULL);
}
cur = CUR;
while (((cur >= 'a') && (cur <= 'z')) ||
((cur >= 'A') && (cur <= 'Z')) ||
((cur >= '0') && (cur <= '9')) ||
(cur == '_') || (cur == '.') ||
(cur == ':') || (cur == '-')) {
if (len + 1 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
return(NULL);
}
}
buf[len++] = cur;
NEXT;
cur=CUR;
}
buf[len] = 0;
return(buf);
}
xmlChar *
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
xmlChar *version = NULL;
const xmlChar *q;
if ((RAW == 'v') && (NXT(1) == 'e') &&
(NXT(2) == 'r') && (NXT(3) == 's') &&
(NXT(4) == 'i') && (NXT(5) == 'o') &&
(NXT(6) == 'n')) {
SKIP(7);
SKIP_BLANKS;
if (RAW != '=') {
ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseVersionInfo : expected '='\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
NEXT;
SKIP_BLANKS;
if (RAW == '"') {
NEXT;
q = CUR_PTR;
version = xmlParseVersionNum(ctxt);
if (RAW != '"') {
ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"String not closed\n%.50s\n", q);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
} else if (RAW == '\''){
NEXT;
q = CUR_PTR;
version = xmlParseVersionNum(ctxt);
if (RAW != '\'') {
ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"String not closed\n%.50s\n", q);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
} else {
ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseVersionInfo : expected ' or \"\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
return(version);
}
xmlChar *
xmlParseEncName(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = 10;
xmlChar cur;
cur = CUR;
if (((cur >= 'a') && (cur <= 'z')) ||
((cur >= 'A') && (cur <= 'Z'))) {
buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %d byte failed\n", size);
return(NULL);
}
buf[len++] = cur;
NEXT;
cur = CUR;
while (((cur >= 'a') && (cur <= 'z')) ||
((cur >= 'A') && (cur <= 'Z')) ||
((cur >= '0') && (cur <= '9')) ||
(cur == '.') || (cur == '_') ||
(cur == '-')) {
if (len + 1 >= size) {
size *= 2;
buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", size);
return(NULL);
}
}
buf[len++] = cur;
NEXT;
cur = CUR;
if (cur == 0) {
SHRINK;
GROW;
cur = CUR;
}
}
buf[len] = 0;
} else {
ctxt->errNo = XML_ERR_ENCODING_NAME;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
return(buf);
}
xmlChar *
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
xmlChar *encoding = NULL;
const xmlChar *q;
SKIP_BLANKS;
if ((RAW == 'e') && (NXT(1) == 'n') &&
(NXT(2) == 'c') && (NXT(3) == 'o') &&
(NXT(4) == 'd') && (NXT(5) == 'i') &&
(NXT(6) == 'n') && (NXT(7) == 'g')) {
SKIP(8);
SKIP_BLANKS;
if (RAW != '=') {
ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseEncodingDecl : expected '='\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(NULL);
}
NEXT;
SKIP_BLANKS;
if (RAW == '"') {
NEXT;
q = CUR_PTR;
encoding = xmlParseEncName(ctxt);
if (RAW != '"') {
ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"String not closed\n%.50s\n", q);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
} else if (RAW == '\''){
NEXT;
q = CUR_PTR;
encoding = xmlParseEncName(ctxt);
if (RAW != '\'') {
ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"String not closed\n%.50s\n", q);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
} else {
ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlParseEncodingDecl : expected ' or \"\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (encoding != NULL) {
xmlCharEncoding enc;
xmlCharEncodingHandlerPtr handler;
if (ctxt->input->encoding != NULL)
xmlFree((xmlChar *) ctxt->input->encoding);
ctxt->input->encoding = encoding;
enc = xmlParseCharEncoding((const char *) encoding);
if (enc != XML_CHAR_ENCODING_ERROR) {
xmlSwitchEncoding(ctxt, enc);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
ctxt->input->encoding = NULL;
xmlFree(encoding);
return(NULL);
}
} else {
handler = xmlFindCharEncodingHandler((const char *) encoding);
if (handler != NULL) {
xmlSwitchToEncoding(ctxt, handler);
} else {
ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Unsupported encoding %s\n", encoding);
return(NULL);
}
}
}
}
return(encoding);
}
int
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
int standalone = -1;
SKIP_BLANKS;
if ((RAW == 's') && (NXT(1) == 't') &&
(NXT(2) == 'a') && (NXT(3) == 'n') &&
(NXT(4) == 'd') && (NXT(5) == 'a') &&
(NXT(6) == 'l') && (NXT(7) == 'o') &&
(NXT(8) == 'n') && (NXT(9) == 'e')) {
SKIP(10);
SKIP_BLANKS;
if (RAW != '=') {
ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML standalone declaration : expected '='\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
return(standalone);
}
NEXT;
SKIP_BLANKS;
if (RAW == '\''){
NEXT;
if ((RAW == 'n') && (NXT(1) == 'o')) {
standalone = 0;
SKIP(2);
} else if ((RAW == 'y') && (NXT(1) == 'e') &&
(NXT(2) == 's')) {
standalone = 1;
SKIP(3);
} else {
ctxt->errNo = XML_ERR_STANDALONE_VALUE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"standalone accepts only 'yes' or 'no'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (RAW != '\'') {
ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "String not closed\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
} else if (RAW == '"'){
NEXT;
if ((RAW == 'n') && (NXT(1) == 'o')) {
standalone = 0;
SKIP(2);
} else if ((RAW == 'y') && (NXT(1) == 'e') &&
(NXT(2) == 's')) {
standalone = 1;
SKIP(3);
} else {
ctxt->errNo = XML_ERR_STANDALONE_VALUE;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"standalone accepts only 'yes' or 'no'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (RAW != '"') {
ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "String not closed\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else
NEXT;
} else {
ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Standalone value not found\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
}
return(standalone);
}
void
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
xmlChar *version;
SKIP(5);
if (!IS_BLANK(RAW)) {
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
version = xmlParseVersionInfo(ctxt);
if (version == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Malformed declaration expecting version\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else {
if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData, "Unsupported version '%s'\n",
version);
}
if (ctxt->version != NULL)
xmlFree((void *) ctxt->version);
ctxt->version = version;
}
if (!IS_BLANK(RAW)) {
if ((RAW == '?') && (NXT(1) == '>')) {
SKIP(2);
return;
}
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Blank needed here\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
xmlParseEncodingDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
return;
}
if ((ctxt->input->encoding != NULL) && (!IS_BLANK(RAW))) {
if ((RAW == '?') && (NXT(1) == '>')) {
SKIP(2);
return;
}
ctxt->errNo = XML_ERR_SPACE_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Blank needed here\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
SKIP_BLANKS;
ctxt->input->standalone = xmlParseSDDecl(ctxt);
SKIP_BLANKS;
if ((RAW == '?') && (NXT(1) == '>')) {
SKIP(2);
} else if (RAW == '>') {
ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"XML declaration must end-up with '?>'\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
NEXT;
} else {
ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"parsing XML declaration: '?>' expected\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
MOVETO_ENDTAG(CUR_PTR);
NEXT;
}
}
void
xmlParseMisc(xmlParserCtxtPtr ctxt) {
while (((RAW == '<') && (NXT(1) == '?')) ||
((RAW == '<') && (NXT(1) == '!') &&
(NXT(2) == '-') && (NXT(3) == '-')) ||
IS_BLANK(CUR)) {
if ((RAW == '<') && (NXT(1) == '?')) {
xmlParsePI(ctxt);
} else if (IS_BLANK(CUR)) {
NEXT;
} else
xmlParseComment(ctxt);
}
}
int
xmlParseDocument(xmlParserCtxtPtr ctxt) {
xmlChar start[4];
xmlCharEncoding enc;
xmlInitParser();
GROW;
if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
if (ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) {
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
}
if (CUR == 0) {
ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Document is empty\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
GROW;
if ((RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseXMLDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
return(-1);
}
ctxt->standalone = ctxt->input->standalone;
SKIP_BLANKS;
} else {
ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
}
if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
ctxt->sax->startDocument(ctxt->userData);
GROW;
xmlParseMisc(ctxt);
GROW;
if ((RAW == '<') && (NXT(1) == '!') &&
(NXT(2) == 'D') && (NXT(3) == 'O') &&
(NXT(4) == 'C') && (NXT(5) == 'T') &&
(NXT(6) == 'Y') && (NXT(7) == 'P') &&
(NXT(8) == 'E')) {
ctxt->inSubset = 1;
xmlParseDocTypeDecl(ctxt);
if (RAW == '[') {
ctxt->instate = XML_PARSER_DTD;
xmlParseInternalSubset(ctxt);
}
ctxt->inSubset = 2;
if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
ctxt->extSubSystem, ctxt->extSubURI);
ctxt->inSubset = 0;
ctxt->instate = XML_PARSER_PROLOG;
xmlParseMisc(ctxt);
}
GROW;
if (RAW != '<') {
ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Start tag expected, '<' not found\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_EOF;
} else {
ctxt->instate = XML_PARSER_CONTENT;
xmlParseElement(ctxt);
ctxt->instate = XML_PARSER_EPILOG;
xmlParseMisc(ctxt);
if (RAW != 0) {
ctxt->errNo = XML_ERR_DOCUMENT_END;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Extra content at the end of the document\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
ctxt->instate = XML_PARSER_EOF;
}
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
if ((ctxt->myDoc != NULL) &&
(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (! ctxt->wellFormed) {
ctxt->valid = 0;
return(-1);
}
return(0);
}
int
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
xmlChar start[4];
xmlCharEncoding enc;
xmlDefaultSAXHandlerInit();
GROW;
if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
if (CUR == 0) {
ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Document is empty\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
GROW;
if ((RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseXMLDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
return(-1);
}
SKIP_BLANKS;
} else {
ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
}
if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
ctxt->sax->startDocument(ctxt->userData);
ctxt->instate = XML_PARSER_CONTENT;
ctxt->validate = 0;
ctxt->loadsubset = 0;
ctxt->depth = 0;
xmlParseContent(ctxt);
if ((RAW == '<') && (NXT(1) == '/')) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (RAW != 0) {
ctxt->errNo = XML_ERR_EXTRA_CONTENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"extra content at the end of well balanced chunk\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
if (! ctxt->wellFormed) return(-1);
return(0);
}
static int
xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
xmlChar next, xmlChar third) {
int base, len;
xmlParserInputPtr in;
const xmlChar *buf;
in = ctxt->input;
if (in == NULL) return(-1);
base = in->cur - in->base;
if (base < 0) return(-1);
if (ctxt->checkIndex > base)
base = ctxt->checkIndex;
if (in->buf == NULL) {
buf = in->base;
len = in->length;
} else {
buf = in->buf->buffer->content;
len = in->buf->buffer->use;
}
if (third) len -= 2;
else if (next) len --;
for (;base < len;base++) {
if (buf[base] == first) {
if (third != 0) {
if ((buf[base + 1] != next) ||
(buf[base + 2] != third)) continue;
} else if (next != 0) {
if (buf[base + 1] != next) continue;
}
ctxt->checkIndex = 0;
#ifdef DEBUG_PUSH
if (next == 0)
xmlGenericError(xmlGenericErrorContext,
"PP: lookup '%c' found at %d\n",
first, base);
else if (third == 0)
xmlGenericError(xmlGenericErrorContext,
"PP: lookup '%c%c' found at %d\n",
first, next, base);
else
xmlGenericError(xmlGenericErrorContext,
"PP: lookup '%c%c%c' found at %d\n",
first, next, third, base);
#endif
return(base - (in->cur - in->base));
}
}
ctxt->checkIndex = base;
#ifdef DEBUG_PUSH
if (next == 0)
xmlGenericError(xmlGenericErrorContext,
"PP: lookup '%c' failed\n", first);
else if (third == 0)
xmlGenericError(xmlGenericErrorContext,
"PP: lookup '%c%c' failed\n", first, next);
else
xmlGenericError(xmlGenericErrorContext,
"PP: lookup '%c%c%c' failed\n", first, next, third);
#endif
return(-1);
}
static int
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
int ret = 0;
int avail;
xmlChar cur, next;
#ifdef DEBUG_PUSH
switch (ctxt->instate) {
case XML_PARSER_EOF:
xmlGenericError(xmlGenericErrorContext,
"PP: try EOF\n"); break;
case XML_PARSER_START:
xmlGenericError(xmlGenericErrorContext,
"PP: try START\n"); break;
case XML_PARSER_MISC:
xmlGenericError(xmlGenericErrorContext,
"PP: try MISC\n");break;
case XML_PARSER_COMMENT:
xmlGenericError(xmlGenericErrorContext,
"PP: try COMMENT\n");break;
case XML_PARSER_PROLOG:
xmlGenericError(xmlGenericErrorContext,
"PP: try PROLOG\n");break;
case XML_PARSER_START_TAG:
xmlGenericError(xmlGenericErrorContext,
"PP: try START_TAG\n");break;
case XML_PARSER_CONTENT:
xmlGenericError(xmlGenericErrorContext,
"PP: try CONTENT\n");break;
case XML_PARSER_CDATA_SECTION:
xmlGenericError(xmlGenericErrorContext,
"PP: try CDATA_SECTION\n");break;
case XML_PARSER_END_TAG:
xmlGenericError(xmlGenericErrorContext,
"PP: try END_TAG\n");break;
case XML_PARSER_ENTITY_DECL:
xmlGenericError(xmlGenericErrorContext,
"PP: try ENTITY_DECL\n");break;
case XML_PARSER_ENTITY_VALUE:
xmlGenericError(xmlGenericErrorContext,
"PP: try ENTITY_VALUE\n");break;
case XML_PARSER_ATTRIBUTE_VALUE:
xmlGenericError(xmlGenericErrorContext,
"PP: try ATTRIBUTE_VALUE\n");break;
case XML_PARSER_DTD:
xmlGenericError(xmlGenericErrorContext,
"PP: try DTD\n");break;
case XML_PARSER_EPILOG:
xmlGenericError(xmlGenericErrorContext,
"PP: try EPILOG\n");break;
case XML_PARSER_PI:
xmlGenericError(xmlGenericErrorContext,
"PP: try PI\n");break;
case XML_PARSER_IGNORE:
xmlGenericError(xmlGenericErrorContext,
"PP: try IGNORE\n");break;
}
#endif
while (1) {
SHRINK;
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
if (ctxt->input ==NULL) break;
if (ctxt->input->buf == NULL)
avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
else {
if ((ctxt->input->buf->raw != NULL) &&
(ctxt->input->buf->raw->use > 0)) {
int base = ctxt->input->base -
ctxt->input->buf->buffer->content;
int current = ctxt->input->cur - ctxt->input->base;
xmlParserInputBufferPush(ctxt->input->buf, 0, "");
ctxt->input->base = ctxt->input->buf->buffer->content + base;
ctxt->input->cur = ctxt->input->base + current;
ctxt->input->end =
&ctxt->input->buf->buffer->content[
ctxt->input->buf->buffer->use];
}
avail = ctxt->input->buf->buffer->use -
(ctxt->input->cur - ctxt->input->base);
}
if (avail < 1)
goto done;
switch (ctxt->instate) {
case XML_PARSER_EOF:
goto done;
case XML_PARSER_START:
if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
xmlChar start[4];
xmlCharEncoding enc;
if (avail < 4)
goto done;
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
break;
}
cur = ctxt->input->cur[0];
next = ctxt->input->cur[1];
if (cur == 0) {
if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
ctxt->sax->setDocumentLocator(ctxt->userData,
&xmlDefaultSAXLocator);
ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData, "Document is empty\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_EOF;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering EOF\n");
#endif
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
goto done;
}
if ((cur == '<') && (next == '?')) {
if (avail < 5) return(ret);
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
return(ret);
if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
ctxt->sax->setDocumentLocator(ctxt->userData,
&xmlDefaultSAXLocator);
if ((ctxt->input->cur[2] == 'x') &&
(ctxt->input->cur[3] == 'm') &&
(ctxt->input->cur[4] == 'l') &&
(IS_BLANK(ctxt->input->cur[5]))) {
ret += 5;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing XML Decl\n");
#endif
xmlParseXMLDecl(ctxt);
if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
ctxt->instate = XML_PARSER_EOF;
return(0);
}
ctxt->standalone = ctxt->input->standalone;
if ((ctxt->encoding == NULL) &&
(ctxt->input->encoding != NULL))
ctxt->encoding = xmlStrdup(ctxt->input->encoding);
if ((ctxt->sax) && (ctxt->sax->startDocument) &&
(!ctxt->disableSAX))
ctxt->sax->startDocument(ctxt->userData);
ctxt->instate = XML_PARSER_MISC;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering MISC\n");
#endif
} else {
ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
if ((ctxt->sax) && (ctxt->sax->startDocument) &&
(!ctxt->disableSAX))
ctxt->sax->startDocument(ctxt->userData);
ctxt->instate = XML_PARSER_MISC;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering MISC\n");
#endif
}
} else {
if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
ctxt->sax->setDocumentLocator(ctxt->userData,
&xmlDefaultSAXLocator);
ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
if ((ctxt->sax) && (ctxt->sax->startDocument) &&
(!ctxt->disableSAX))
ctxt->sax->startDocument(ctxt->userData);
ctxt->instate = XML_PARSER_MISC;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering MISC\n");
#endif
}
break;
case XML_PARSER_MISC:
SKIP_BLANKS;
if (ctxt->input->buf == NULL)
avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
else
avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
if (avail < 2)
goto done;
cur = ctxt->input->cur[0];
next = ctxt->input->cur[1];
if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing PI\n");
#endif
xmlParsePI(ctxt);
} else if ((cur == '<') && (next == '!') &&
(ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing Comment\n");
#endif
xmlParseComment(ctxt);
ctxt->instate = XML_PARSER_MISC;
} else if ((cur == '<') && (next == '!') &&
(ctxt->input->cur[2] == 'D') && (ctxt->input->cur[3] == 'O') &&
(ctxt->input->cur[4] == 'C') && (ctxt->input->cur[5] == 'T') &&
(ctxt->input->cur[6] == 'Y') && (ctxt->input->cur[7] == 'P') &&
(ctxt->input->cur[8] == 'E')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing internal subset\n");
#endif
ctxt->inSubset = 1;
xmlParseDocTypeDecl(ctxt);
if (RAW == '[') {
ctxt->instate = XML_PARSER_DTD;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering DTD\n");
#endif
} else {
ctxt->inSubset = 2;
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->externalSubset != NULL))
ctxt->sax->externalSubset(ctxt->userData,
ctxt->intSubName, ctxt->extSubSystem,
ctxt->extSubURI);
ctxt->inSubset = 0;
ctxt->instate = XML_PARSER_PROLOG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering PROLOG\n");
#endif
}
} else if ((cur == '<') && (next == '!') &&
(avail < 9)) {
goto done;
} else {
ctxt->instate = XML_PARSER_START_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering START_TAG\n");
#endif
}
break;
case XML_PARSER_IGNORE:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == IGNORE");
ctxt->instate = XML_PARSER_DTD;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering DTD\n");
#endif
break;
case XML_PARSER_PROLOG:
SKIP_BLANKS;
if (ctxt->input->buf == NULL)
avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
else
avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
if (avail < 2)
goto done;
cur = ctxt->input->cur[0];
next = ctxt->input->cur[1];
if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing PI\n");
#endif
xmlParsePI(ctxt);
} else if ((cur == '<') && (next == '!') &&
(ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing Comment\n");
#endif
xmlParseComment(ctxt);
ctxt->instate = XML_PARSER_PROLOG;
} else if ((cur == '<') && (next == '!') &&
(avail < 4)) {
goto done;
} else {
ctxt->instate = XML_PARSER_START_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering START_TAG\n");
#endif
}
break;
case XML_PARSER_EPILOG:
SKIP_BLANKS;
if (ctxt->input->buf == NULL)
avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
else
avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
if (avail < 2)
goto done;
cur = ctxt->input->cur[0];
next = ctxt->input->cur[1];
if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing PI\n");
#endif
xmlParsePI(ctxt);
ctxt->instate = XML_PARSER_EPILOG;
} else if ((cur == '<') && (next == '!') &&
(ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing Comment\n");
#endif
xmlParseComment(ctxt);
ctxt->instate = XML_PARSER_EPILOG;
} else if ((cur == '<') && (next == '!') &&
(avail < 4)) {
goto done;
} else {
ctxt->errNo = XML_ERR_DOCUMENT_END;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Extra content at the end of the document\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_EOF;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering EOF\n");
#endif
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
goto done;
}
break;
case XML_PARSER_START_TAG: {
xmlChar *name, *oldname;
if ((avail < 2) && (ctxt->inputNr == 1))
goto done;
cur = ctxt->input->cur[0];
if (cur != '<') {
ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Start tag expect, '<' not found\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_EOF;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering EOF\n");
#endif
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
goto done;
}
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
goto done;
if (ctxt->spaceNr == 0)
spacePush(ctxt, -1);
else
spacePush(ctxt, *ctxt->space);
name = xmlParseStartTag(ctxt);
if (name == NULL) {
spacePop(ctxt);
ctxt->instate = XML_PARSER_EOF;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering EOF\n");
#endif
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
goto done;
}
namePush(ctxt, xmlStrdup(name));
if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
ctxt->node && (ctxt->node == ctxt->myDoc->children))
ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
if ((RAW == '/') && (NXT(1) == '>')) {
SKIP(2);
if ((ctxt->sax != NULL) &&
(ctxt->sax->endElement != NULL) && (!ctxt->disableSAX))
ctxt->sax->endElement(ctxt->userData, name);
xmlFree(name);
oldname = namePop(ctxt);
spacePop(ctxt);
if (oldname != NULL) {
#ifdef DEBUG_STACK
xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
#endif
xmlFree(oldname);
}
if (ctxt->name == NULL) {
ctxt->instate = XML_PARSER_EPILOG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering EPILOG\n");
#endif
} else {
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CONTENT\n");
#endif
}
break;
}
if (RAW == '>') {
NEXT;
} else {
ctxt->errNo = XML_ERR_GT_REQUIRED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Couldn't find end of Start Tag %s\n",
name);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
nodePop(ctxt);
oldname = namePop(ctxt);
spacePop(ctxt);
if (oldname != NULL) {
#ifdef DEBUG_STACK
xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
#endif
xmlFree(oldname);
}
}
xmlFree(name);
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CONTENT\n");
#endif
break;
}
case XML_PARSER_CONTENT: {
const xmlChar *test;
int cons;
if ((avail < 2) && (ctxt->inputNr == 1))
goto done;
cur = ctxt->input->cur[0];
next = ctxt->input->cur[1];
test = CUR_PTR;
cons = ctxt->input->consumed;
if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing PI\n");
#endif
xmlParsePI(ctxt);
} else if ((cur == '<') && (next == '!') &&
(ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing Comment\n");
#endif
xmlParseComment(ctxt);
ctxt->instate = XML_PARSER_CONTENT;
} else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
(ctxt->input->cur[2] == '[') && (NXT(3) == 'C') &&
(ctxt->input->cur[4] == 'D') && (NXT(5) == 'A') &&
(ctxt->input->cur[6] == 'T') && (NXT(7) == 'A') &&
(ctxt->input->cur[8] == '[')) {
SKIP(9);
ctxt->instate = XML_PARSER_CDATA_SECTION;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CDATA_SECTION\n");
#endif
break;
} else if ((cur == '<') && (next == '!') &&
(avail < 9)) {
goto done;
} else if ((cur == '<') && (next == '/')) {
ctxt->instate = XML_PARSER_END_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering END_TAG\n");
#endif
break;
} else if (cur == '<') {
ctxt->instate = XML_PARSER_START_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering START_TAG\n");
#endif
break;
} else if (cur == '&') {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing Reference\n");
#endif
xmlParseReference(ctxt);
} else {
if ((ctxt->inputNr == 1) &&
(avail < XML_PARSER_BIG_BUFFER_SIZE)) {
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '<', 0, 0) < 0))
goto done;
}
ctxt->checkIndex = 0;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: Parsing char data\n");
#endif
xmlParseCharData(ctxt, 0);
}
while ((RAW == 0) && (ctxt->inputNr > 1))
xmlPopInput(ctxt);
if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"detected an error in element content\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_EOF;
break;
}
break;
}
case XML_PARSER_CDATA_SECTION: {
int base;
base = xmlParseLookupSequence(ctxt, ']', ']', '>');
if (base < 0) {
if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
if (ctxt->sax->cdataBlock != NULL)
ctxt->sax->cdataBlock(ctxt->userData, ctxt->input->cur,
XML_PARSER_BIG_BUFFER_SIZE);
}
SKIP(XML_PARSER_BIG_BUFFER_SIZE);
ctxt->checkIndex = 0;
}
goto done;
} else {
if ((ctxt->sax != NULL) && (base > 0) &&
(!ctxt->disableSAX)) {
if (ctxt->sax->cdataBlock != NULL)
ctxt->sax->cdataBlock(ctxt->userData,
ctxt->input->cur, base);
}
SKIP(base + 3);
ctxt->checkIndex = 0;
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CONTENT\n");
#endif
}
break;
}
case XML_PARSER_END_TAG:
if (avail < 2)
goto done;
if ((!terminate) &&
(xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
goto done;
xmlParseEndTag(ctxt);
if (ctxt->name == NULL) {
ctxt->instate = XML_PARSER_EPILOG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering EPILOG\n");
#endif
} else {
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CONTENT\n");
#endif
}
break;
case XML_PARSER_DTD: {
int base, i;
xmlChar *buf;
xmlChar quote = 0;
base = ctxt->input->cur - ctxt->input->base;
if (base < 0) return(0);
if (ctxt->checkIndex > base)
base = ctxt->checkIndex;
buf = ctxt->input->buf->buffer->content;
for (;(unsigned int) base < ctxt->input->buf->buffer->use;
base++) {
if (quote != 0) {
if (buf[base] == quote)
quote = 0;
continue;
}
if (buf[base] == '"') {
quote = '"';
continue;
}
if (buf[base] == '\'') {
quote = '\'';
continue;
}
if (buf[base] == ']') {
if ((unsigned int) base +1 >=
ctxt->input->buf->buffer->use)
break;
if (buf[base + 1] == ']') {
base++;
continue;
}
for (i = 0;
(unsigned int) base + i < ctxt->input->buf->buffer->use;
i++) {
if (buf[base + i] == '>')
goto found_end_int_subset;
}
break;
}
}
if (quote == 0)
ctxt->checkIndex = base;
#ifdef DEBUG_PUSH
if (next == 0)
xmlGenericError(xmlGenericErrorContext,
"PP: lookup of int subset end filed\n");
#endif
goto done;
found_end_int_subset:
xmlParseInternalSubset(ctxt);
ctxt->inSubset = 2;
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->externalSubset != NULL))
ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
ctxt->extSubSystem, ctxt->extSubURI);
ctxt->inSubset = 0;
ctxt->instate = XML_PARSER_PROLOG;
ctxt->checkIndex = 0;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering PROLOG\n");
#endif
break;
}
case XML_PARSER_COMMENT:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == COMMENT\n");
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CONTENT\n");
#endif
break;
case XML_PARSER_PI:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == PI\n");
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering CONTENT\n");
#endif
break;
case XML_PARSER_ENTITY_DECL:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == ENTITY_DECL\n");
ctxt->instate = XML_PARSER_DTD;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering DTD\n");
#endif
break;
case XML_PARSER_ENTITY_VALUE:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == ENTITY_VALUE\n");
ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering DTD\n");
#endif
break;
case XML_PARSER_ATTRIBUTE_VALUE:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == ATTRIBUTE_VALUE\n");
ctxt->instate = XML_PARSER_START_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering START_TAG\n");
#endif
break;
case XML_PARSER_SYSTEM_LITERAL:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == SYSTEM_LITERAL\n");
ctxt->instate = XML_PARSER_START_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering START_TAG\n");
#endif
break;
case XML_PARSER_PUBLIC_LITERAL:
xmlGenericError(xmlGenericErrorContext,
"PP: internal error, state == PUBLIC_LITERAL\n");
ctxt->instate = XML_PARSER_START_TAG;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"PP: entering START_TAG\n");
#endif
break;
}
}
done:
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
#endif
return(ret);
}
int
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
int terminate) {
if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
(ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) {
int base = ctxt->input->base - ctxt->input->buf->buffer->content;
int cur = ctxt->input->cur - ctxt->input->base;
xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
ctxt->input->base = ctxt->input->buf->buffer->content + base;
ctxt->input->cur = ctxt->input->base + cur;
ctxt->input->end =
&ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
#endif
if ((terminate) || (ctxt->input->buf->buffer->use > 80))
xmlParseTryOrFinish(ctxt, terminate);
} else if (ctxt->instate != XML_PARSER_EOF) {
if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
xmlParserInputBufferPtr in = ctxt->input->buf;
if ((in->encoder != NULL) && (in->buffer != NULL) &&
(in->raw != NULL)) {
int nbchars;
nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
if (nbchars < 0) {
xmlGenericError(xmlGenericErrorContext,
"xmlParseChunk: encoder error\n");
return(XML_ERR_INVALID_ENCODING);
}
}
}
}
xmlParseTryOrFinish(ctxt, terminate);
if (terminate) {
int avail = 0;
if (ctxt->input->buf == NULL)
avail = ctxt->input->length -
(ctxt->input->cur - ctxt->input->base);
else
avail = ctxt->input->buf->buffer->use -
(ctxt->input->cur - ctxt->input->base);
if ((ctxt->instate != XML_PARSER_EOF) &&
(ctxt->instate != XML_PARSER_EPILOG)) {
ctxt->errNo = XML_ERR_DOCUMENT_END;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Extra content at the end of the document\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) {
ctxt->errNo = XML_ERR_DOCUMENT_END;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Extra content at the end of the document\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (ctxt->instate != XML_PARSER_EOF) {
if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
ctxt->sax->endDocument(ctxt->userData);
}
ctxt->instate = XML_PARSER_EOF;
}
return((xmlParserErrors) ctxt->errNo);
}
void
xmlStopParser(xmlParserCtxtPtr ctxt) {
ctxt->instate = XML_PARSER_EOF;
if (ctxt->input != NULL)
ctxt->input->cur = BAD_CAST"";
}
xmlParserCtxtPtr
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
const char *chunk, int size, const char *filename) {
xmlParserCtxtPtr ctxt;
xmlParserInputPtr inputStream;
xmlParserInputBufferPtr buf;
xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
if ((chunk != NULL) && (size >= 4))
enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
buf = xmlAllocParserInputBuffer(enc);
if (buf == NULL) return(NULL);
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
xmlFree(buf);
return(NULL);
}
if (sax != NULL) {
if (ctxt->sax != &xmlDefaultSAXHandler)
xmlFree(ctxt->sax);
ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
if (ctxt->sax == NULL) {
xmlFree(buf);
xmlFree(ctxt);
return(NULL);
}
memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
if (user_data != NULL)
ctxt->userData = user_data;
}
if (filename == NULL) {
ctxt->directory = NULL;
} else {
ctxt->directory = xmlParserGetDirectory(filename);
}
inputStream = xmlNewInputStream(ctxt);
if (inputStream == NULL) {
xmlFreeParserCtxt(ctxt);
return(NULL);
}
if (filename == NULL)
inputStream->filename = NULL;
else
inputStream->filename = (char *)
xmlCanonicPath((const xmlChar *) filename);
inputStream->buf = buf;
inputStream->base = inputStream->buf->buffer->content;
inputStream->cur = inputStream->buf->buffer->content;
inputStream->end =
&inputStream->buf->buffer->content[inputStream->buf->buffer->use];
inputPush(ctxt, inputStream);
if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
(ctxt->input->buf != NULL)) {
int base = ctxt->input->base - ctxt->input->buf->buffer->content;
int cur = ctxt->input->cur - ctxt->input->base;
xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
ctxt->input->base = ctxt->input->buf->buffer->content + base;
ctxt->input->cur = ctxt->input->base + cur;
ctxt->input->end =
&ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
#endif
}
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
return(ctxt);
}
xmlParserCtxtPtr
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
void *ioctx, xmlCharEncoding enc) {
xmlParserCtxtPtr ctxt;
xmlParserInputPtr inputStream;
xmlParserInputBufferPtr buf;
buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
if (buf == NULL) return(NULL);
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
xmlFree(buf);
return(NULL);
}
if (sax != NULL) {
if (ctxt->sax != &xmlDefaultSAXHandler)
xmlFree(ctxt->sax);
ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
if (ctxt->sax == NULL) {
xmlFree(buf);
xmlFree(ctxt);
return(NULL);
}
memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
if (user_data != NULL)
ctxt->userData = user_data;
}
inputStream = xmlNewIOInputStream(ctxt, buf, enc);
if (inputStream == NULL) {
xmlFreeParserCtxt(ctxt);
return(NULL);
}
inputPush(ctxt, inputStream);
return(ctxt);
}
xmlDtdPtr
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
xmlCharEncoding enc) {
xmlDtdPtr ret = NULL;
xmlParserCtxtPtr ctxt;
xmlParserInputPtr pinput = NULL;
xmlChar start[4];
if (input == NULL)
return(NULL);
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
return(NULL);
}
if (sax != NULL) {
if (ctxt->sax != NULL)
xmlFree(ctxt->sax);
ctxt->sax = sax;
ctxt->userData = NULL;
}
pinput = xmlNewIOInputStream(ctxt, input, enc);
if (pinput == NULL) {
if (sax != NULL) ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(NULL);
}
xmlPushInput(ctxt, pinput);
pinput->filename = NULL;
pinput->line = 1;
pinput->col = 1;
pinput->base = ctxt->input->cur;
pinput->cur = ctxt->input->cur;
pinput->free = NULL;
ctxt->inSubset = 2;
ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
BAD_CAST "none", BAD_CAST "none");
if (enc == XML_CHAR_ENCODING_NONE) {
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
}
xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
if (ctxt->myDoc != NULL) {
if (ctxt->wellFormed) {
ret = ctxt->myDoc->extSubset;
ctxt->myDoc->extSubset = NULL;
} else {
ret = NULL;
}
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (sax != NULL) ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(ret);
}
xmlDtdPtr
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
const xmlChar *SystemID) {
xmlDtdPtr ret = NULL;
xmlParserCtxtPtr ctxt;
xmlParserInputPtr input = NULL;
xmlCharEncoding enc;
if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
return(NULL);
}
if (sax != NULL) {
if (ctxt->sax != NULL)
xmlFree(ctxt->sax);
ctxt->sax = sax;
ctxt->userData = NULL;
}
if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
if (input == NULL) {
if (sax != NULL) ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(NULL);
}
xmlPushInput(ctxt, input);
enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
xmlSwitchEncoding(ctxt, enc);
if (input->filename == NULL)
input->filename = (char *) xmlStrdup(SystemID);
input->line = 1;
input->col = 1;
input->base = ctxt->input->cur;
input->cur = ctxt->input->cur;
input->free = NULL;
ctxt->inSubset = 2;
ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
ExternalID, SystemID);
xmlParseExternalSubset(ctxt, ExternalID, SystemID);
if (ctxt->myDoc != NULL) {
if (ctxt->wellFormed) {
ret = ctxt->myDoc->extSubset;
ctxt->myDoc->extSubset = NULL;
} else {
ret = NULL;
}
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (sax != NULL) ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(ret);
}
xmlDtdPtr
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
}
int
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
const xmlChar *ID, xmlNodePtr *lst) {
xmlParserCtxtPtr ctxt;
xmlDocPtr newDoc;
xmlSAXHandlerPtr oldsax = NULL;
int ret = 0;
xmlChar start[4];
xmlCharEncoding enc;
if (ctx->depth > 40) {
return(XML_ERR_ENTITY_LOOP);
}
if (lst != NULL)
*lst = NULL;
if ((URL == NULL) && (ID == NULL))
return(-1);
if (ctx->myDoc == NULL)
return(-1);
ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
if (ctxt == NULL) return(-1);
ctxt->userData = ctxt;
ctxt->_private = ctx->_private;
oldsax = ctxt->sax;
ctxt->sax = ctx->sax;
newDoc = xmlNewDoc(BAD_CAST "1.0");
if (newDoc == NULL) {
xmlFreeParserCtxt(ctxt);
return(-1);
}
if (ctx->myDoc != NULL) {
newDoc->intSubset = ctx->myDoc->intSubset;
newDoc->extSubset = ctx->myDoc->extSubset;
}
if (ctx->myDoc->URL != NULL) {
newDoc->URL = xmlStrdup(ctx->myDoc->URL);
}
newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
if (newDoc->children == NULL) {
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
xmlFreeDoc(newDoc);
return(-1);
}
nodePush(ctxt, newDoc->children);
if (ctx->myDoc == NULL) {
ctxt->myDoc = newDoc;
} else {
ctxt->myDoc = ctx->myDoc;
newDoc->children->doc = ctx->myDoc;
}
GROW
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
if ((RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseTextDecl(ctxt);
}
ctxt->instate = XML_PARSER_CONTENT;
ctxt->validate = ctx->validate;
ctxt->loadsubset = ctx->loadsubset;
ctxt->depth = ctx->depth + 1;
ctxt->replaceEntities = ctx->replaceEntities;
if (ctxt->validate) {
ctxt->vctxt.error = ctx->vctxt.error;
ctxt->vctxt.warning = ctx->vctxt.warning;
} else {
ctxt->vctxt.error = NULL;
ctxt->vctxt.warning = NULL;
}
ctxt->vctxt.nodeTab = NULL;
ctxt->vctxt.nodeNr = 0;
ctxt->vctxt.nodeMax = 0;
ctxt->vctxt.node = NULL;
xmlParseContent(ctxt);
if ((RAW == '<') && (NXT(1) == '/')) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (RAW != 0) {
ctxt->errNo = XML_ERR_EXTRA_CONTENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"extra content at the end of well balanced chunk\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (ctxt->node != newDoc->children) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (!ctxt->wellFormed) {
if (ctxt->errNo == 0)
ret = 1;
else
ret = ctxt->errNo;
} else {
if (lst != NULL) {
xmlNodePtr cur;
cur = newDoc->children->children;
*lst = cur;
while (cur != NULL) {
cur->parent = NULL;
cur = cur->next;
}
newDoc->children->children = NULL;
}
ret = 0;
}
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
xmlFreeDoc(newDoc);
return(ret);
}
static int
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
xmlSAXHandlerPtr sax,
void *user_data, int depth, const xmlChar *URL,
const xmlChar *ID, xmlNodePtr *list) {
xmlParserCtxtPtr ctxt;
xmlDocPtr newDoc;
xmlSAXHandlerPtr oldsax = NULL;
int ret = 0;
xmlChar start[4];
xmlCharEncoding enc;
if (depth > 40) {
return(XML_ERR_ENTITY_LOOP);
}
if (list != NULL)
*list = NULL;
if ((URL == NULL) && (ID == NULL))
return(-1);
if (doc == NULL)
return(-1);
ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
if (ctxt == NULL) return(-1);
ctxt->userData = ctxt;
if (oldctxt != NULL) {
ctxt->_private = oldctxt->_private;
ctxt->loadsubset = oldctxt->loadsubset;
ctxt->validate = oldctxt->validate;
ctxt->external = oldctxt->external;
ctxt->record_info = oldctxt->record_info;
ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
ctxt->node_seq.length = oldctxt->node_seq.length;
ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
} else {
ctxt->_private = NULL;
ctxt->validate = 0;
ctxt->external = 2;
ctxt->loadsubset = 0;
}
if (sax != NULL) {
oldsax = ctxt->sax;
ctxt->sax = sax;
if (user_data != NULL)
ctxt->userData = user_data;
}
newDoc = xmlNewDoc(BAD_CAST "1.0");
if (newDoc == NULL) {
ctxt->node_seq.maximum = 0;
ctxt->node_seq.length = 0;
ctxt->node_seq.buffer = NULL;
xmlFreeParserCtxt(ctxt);
return(-1);
}
if (doc != NULL) {
newDoc->intSubset = doc->intSubset;
newDoc->extSubset = doc->extSubset;
}
if (doc->URL != NULL) {
newDoc->URL = xmlStrdup(doc->URL);
}
newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
if (newDoc->children == NULL) {
if (sax != NULL)
ctxt->sax = oldsax;
ctxt->node_seq.maximum = 0;
ctxt->node_seq.length = 0;
ctxt->node_seq.buffer = NULL;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
xmlFreeDoc(newDoc);
return(-1);
}
nodePush(ctxt, newDoc->children);
if (doc == NULL) {
ctxt->myDoc = newDoc;
} else {
ctxt->myDoc = doc;
newDoc->children->doc = doc;
}
GROW;
start[0] = RAW;
start[1] = NXT(1);
start[2] = NXT(2);
start[3] = NXT(3);
enc = xmlDetectCharEncoding(start, 4);
if (enc != XML_CHAR_ENCODING_NONE) {
xmlSwitchEncoding(ctxt, enc);
}
if ((RAW == '<') && (NXT(1) == '?') &&
(NXT(2) == 'x') && (NXT(3) == 'm') &&
(NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
xmlParseTextDecl(ctxt);
}
ctxt->instate = XML_PARSER_CONTENT;
ctxt->depth = depth;
xmlParseContent(ctxt);
if ((RAW == '<') && (NXT(1) == '/')) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (RAW != 0) {
ctxt->errNo = XML_ERR_EXTRA_CONTENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"extra content at the end of well balanced chunk\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (ctxt->node != newDoc->children) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (!ctxt->wellFormed) {
if (ctxt->errNo == 0)
ret = 1;
else
ret = ctxt->errNo;
} else {
if (list != NULL) {
xmlNodePtr cur;
cur = newDoc->children->children;
*list = cur;
while (cur != NULL) {
cur->parent = NULL;
cur = cur->next;
}
newDoc->children->children = NULL;
}
ret = 0;
}
if (sax != NULL)
ctxt->sax = oldsax;
oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
oldctxt->node_seq.length = ctxt->node_seq.length;
oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
ctxt->node_seq.maximum = 0;
ctxt->node_seq.length = 0;
ctxt->node_seq.buffer = NULL;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
xmlFreeDoc(newDoc);
return(ret);
}
int
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
ID, lst));
}
int
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
depth, string, lst, 0 );
}
static int
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
const xmlChar *string, void *user_data, xmlNodePtr *lst) {
xmlParserCtxtPtr ctxt;
xmlDocPtr newDoc = NULL;
xmlSAXHandlerPtr oldsax = NULL;
xmlNodePtr content = NULL;
int size;
int ret = 0;
if (oldctxt->depth > 40) {
return(XML_ERR_ENTITY_LOOP);
}
if (lst != NULL)
*lst = NULL;
if (string == NULL)
return(-1);
size = xmlStrlen(string);
ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
if (ctxt == NULL) return(-1);
if (user_data != NULL)
ctxt->userData = user_data;
else
ctxt->userData = ctxt;
oldsax = ctxt->sax;
ctxt->sax = oldctxt->sax;
ctxt->_private = oldctxt->_private;
if (oldctxt->myDoc == NULL) {
newDoc = xmlNewDoc(BAD_CAST "1.0");
if (newDoc == NULL) {
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
return(-1);
}
ctxt->myDoc = newDoc;
} else {
ctxt->myDoc = oldctxt->myDoc;
content = ctxt->myDoc->children;
}
ctxt->myDoc->children = xmlNewDocNode(ctxt->myDoc, NULL,
BAD_CAST "pseudoroot", NULL);
if (ctxt->myDoc->children == NULL) {
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
if (newDoc != NULL)
xmlFreeDoc(newDoc);
return(-1);
}
nodePush(ctxt, ctxt->myDoc->children);
ctxt->instate = XML_PARSER_CONTENT;
ctxt->depth = oldctxt->depth + 1;
ctxt->validate = 0;
ctxt->loadsubset = oldctxt->loadsubset;
xmlParseContent(ctxt);
if ((RAW == '<') && (NXT(1) == '/')) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (RAW != 0) {
ctxt->errNo = XML_ERR_EXTRA_CONTENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"extra content at the end of well balanced chunk\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (ctxt->node != ctxt->myDoc->children) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (!ctxt->wellFormed) {
if (ctxt->errNo == 0)
ret = 1;
else
ret = ctxt->errNo;
} else {
ret = 0;
}
if ((lst != NULL) && (ret == 0)) {
xmlNodePtr cur;
cur = ctxt->myDoc->children->children;
*lst = cur;
while (cur != NULL) {
if (oldctxt->validate && oldctxt->wellFormed &&
oldctxt->myDoc && oldctxt->myDoc->intSubset) {
oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
oldctxt->myDoc, cur);
}
cur->parent = NULL;
cur = cur->next;
}
ctxt->myDoc->children->children = NULL;
}
if (ctxt->myDoc != NULL) {
xmlFreeNode(ctxt->myDoc->children);
ctxt->myDoc->children = content;
}
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
if (newDoc != NULL)
xmlFreeDoc(newDoc);
return(ret);
}
int
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
int recover) {
xmlParserCtxtPtr ctxt;
xmlDocPtr newDoc;
xmlSAXHandlerPtr oldsax = NULL;
xmlNodePtr content;
int size;
int ret = 0;
if (depth > 40) {
return(XML_ERR_ENTITY_LOOP);
}
if (lst != NULL)
*lst = NULL;
if (string == NULL)
return(-1);
size = xmlStrlen(string);
ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
if (ctxt == NULL) return(-1);
ctxt->userData = ctxt;
if (sax != NULL) {
oldsax = ctxt->sax;
ctxt->sax = sax;
if (user_data != NULL)
ctxt->userData = user_data;
}
newDoc = xmlNewDoc(BAD_CAST "1.0");
if (newDoc == NULL) {
xmlFreeParserCtxt(ctxt);
return(-1);
}
if (doc != NULL) {
newDoc->intSubset = doc->intSubset;
newDoc->extSubset = doc->extSubset;
}
newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
if (newDoc->children == NULL) {
if (sax != NULL)
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
xmlFreeDoc(newDoc);
return(-1);
}
nodePush(ctxt, newDoc->children);
if (doc == NULL) {
ctxt->myDoc = newDoc;
} else {
ctxt->myDoc = newDoc;
newDoc->children->doc = doc;
}
ctxt->instate = XML_PARSER_CONTENT;
ctxt->depth = depth;
ctxt->validate = 0;
ctxt->loadsubset = 0;
if ( doc != NULL ){
content = doc->children;
doc->children = NULL;
xmlParseContent(ctxt);
doc->children = content;
}
else {
xmlParseContent(ctxt);
}
if ((RAW == '<') && (NXT(1) == '/')) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
} else if (RAW != 0) {
ctxt->errNo = XML_ERR_EXTRA_CONTENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"extra content at the end of well balanced chunk\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (ctxt->node != newDoc->children) {
ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"chunk is not well balanced\n");
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
}
if (!ctxt->wellFormed) {
if (ctxt->errNo == 0)
ret = 1;
else
ret = ctxt->errNo;
} else {
ret = 0;
}
if (lst != NULL && (ret == 0 || recover == 1)) {
xmlNodePtr cur;
cur = newDoc->children->children;
*lst = cur;
while (cur != NULL) {
cur->parent = NULL;
cur = cur->next;
}
newDoc->children->children = NULL;
}
if (sax != NULL)
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
xmlFreeDoc(newDoc);
return(ret);
}
xmlDocPtr
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
xmlDocPtr ret;
xmlParserCtxtPtr ctxt;
char *directory = NULL;
ctxt = xmlCreateFileParserCtxt(filename);
if (ctxt == NULL) {
return(NULL);
}
if (sax != NULL) {
if (ctxt->sax != NULL)
xmlFree(ctxt->sax);
ctxt->sax = sax;
ctxt->userData = NULL;
}
if ((ctxt->directory == NULL) && (directory == NULL))
directory = xmlParserGetDirectory(filename);
xmlParseExtParsedEnt(ctxt);
if (ctxt->wellFormed)
ret = ctxt->myDoc;
else {
ret = NULL;
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (sax != NULL)
ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(ret);
}
xmlDocPtr
xmlParseEntity(const char *filename) {
return(xmlSAXParseEntity(NULL, filename));
}
xmlParserCtxtPtr
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
const xmlChar *base) {
xmlParserCtxtPtr ctxt;
xmlParserInputPtr inputStream;
char *directory = NULL;
xmlChar *uri;
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
return(NULL);
}
uri = xmlBuildURI(URL, base);
if (uri == NULL) {
inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
if (inputStream == NULL) {
xmlFreeParserCtxt(ctxt);
return(NULL);
}
inputPush(ctxt, inputStream);
if ((ctxt->directory == NULL) && (directory == NULL))
directory = xmlParserGetDirectory((char *)URL);
if ((ctxt->directory == NULL) && (directory != NULL))
ctxt->directory = directory;
} else {
inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
if (inputStream == NULL) {
xmlFree(uri);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
inputPush(ctxt, inputStream);
if ((ctxt->directory == NULL) && (directory == NULL))
directory = xmlParserGetDirectory((char *)uri);
if ((ctxt->directory == NULL) && (directory != NULL))
ctxt->directory = directory;
xmlFree(uri);
}
return(ctxt);
}
xmlParserCtxtPtr
xmlCreateFileParserCtxt(const char *filename)
{
xmlParserCtxtPtr ctxt;
xmlParserInputPtr inputStream;
char *canonicFilename;
char *directory = NULL;
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
if (xmlDefaultSAXHandler.error != NULL) {
xmlDefaultSAXHandler.error(NULL, "out of memory\n");
}
return(NULL);
}
canonicFilename = (char *) xmlCanonicPath((const xmlChar *) filename);
if (canonicFilename == NULL) {
if (xmlDefaultSAXHandler.error != NULL) {
xmlDefaultSAXHandler.error(NULL, "out of memory\n");
}
return(NULL);
}
inputStream = xmlLoadExternalEntity(canonicFilename, NULL, ctxt);
xmlFree(canonicFilename);
if (inputStream == NULL) {
xmlFreeParserCtxt(ctxt);
return(NULL);
}
inputPush(ctxt, inputStream);
if ((ctxt->directory == NULL) && (directory == NULL))
directory = xmlParserGetDirectory(filename);
if ((ctxt->directory == NULL) && (directory != NULL))
ctxt->directory = directory;
return(ctxt);
}
xmlDocPtr
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
int recovery, void *data) {
xmlDocPtr ret;
xmlParserCtxtPtr ctxt;
char *directory = NULL;
xmlInitParser();
ctxt = xmlCreateFileParserCtxt(filename);
if (ctxt == NULL) {
return(NULL);
}
if (sax != NULL) {
if (ctxt->sax != NULL)
xmlFree(ctxt->sax);
ctxt->sax = sax;
}
if (data!=NULL) {
ctxt->_private=data;
}
if ((ctxt->directory == NULL) && (directory == NULL))
directory = xmlParserGetDirectory(filename);
if ((ctxt->directory == NULL) && (directory != NULL))
ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
ctxt->recovery = recovery;
xmlParseDocument(ctxt);
if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
else {
ret = NULL;
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (sax != NULL)
ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(ret);
}
xmlDocPtr
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
int recovery) {
return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
}
xmlDocPtr
xmlRecoverDoc(xmlChar *cur) {
return(xmlSAXParseDoc(NULL, cur, 1));
}
xmlDocPtr
xmlParseFile(const char *filename) {
return(xmlSAXParseFile(NULL, filename, 0));
}
xmlDocPtr
xmlRecoverFile(const char *filename) {
return(xmlSAXParseFile(NULL, filename, 1));
}
void
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
const char* filename)
{
xmlParserInputPtr input;
input = xmlNewInputStream(ctxt);
if (input == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc");
xmlFree(ctxt);
return;
}
xmlClearParserCtxt(ctxt);
if (filename != NULL)
input->filename = xmlMemStrdup(filename);
input->base = buffer;
input->cur = buffer;
input->end = &buffer[xmlStrlen(buffer)];
inputPush(ctxt, input);
}
int
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
const char *filename) {
int ret = 0;
xmlParserCtxtPtr ctxt;
ctxt = xmlCreateFileParserCtxt(filename);
if (ctxt == NULL) return -1;
if (ctxt->sax != &xmlDefaultSAXHandler)
xmlFree(ctxt->sax);
ctxt->sax = sax;
if (user_data != NULL)
ctxt->userData = user_data;
xmlParseDocument(ctxt);
if (ctxt->wellFormed)
ret = 0;
else {
if (ctxt->errNo != 0)
ret = ctxt->errNo;
else
ret = -1;
}
if (sax != NULL)
ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return ret;
}
xmlParserCtxtPtr
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
xmlParserCtxtPtr ctxt;
xmlParserInputPtr input;
xmlParserInputBufferPtr buf;
if (buffer == NULL)
return(NULL);
if (size <= 0)
return(NULL);
ctxt = xmlNewParserCtxt();
if (ctxt == NULL)
return(NULL);
buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
if (buf == NULL) {
xmlFreeParserCtxt(ctxt);
return(NULL);
}
input = xmlNewInputStream(ctxt);
if (input == NULL) {
xmlFreeParserInputBuffer(buf);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
input->filename = NULL;
input->buf = buf;
input->base = input->buf->buffer->content;
input->cur = input->buf->buffer->content;
input->end = &input->buf->buffer->content[input->buf->buffer->use];
inputPush(ctxt, input);
return(ctxt);
}
xmlDocPtr
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
int size, int recovery, void *data) {
xmlDocPtr ret;
xmlParserCtxtPtr ctxt;
ctxt = xmlCreateMemoryParserCtxt(buffer, size);
if (ctxt == NULL) return(NULL);
if (sax != NULL) {
if (ctxt->sax != NULL)
xmlFree(ctxt->sax);
ctxt->sax = sax;
}
if (data!=NULL) {
ctxt->_private=data;
}
xmlParseDocument(ctxt);
if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
else {
ret = NULL;
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (sax != NULL)
ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(ret);
}
xmlDocPtr
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
int size, int recovery) {
return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
}
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
return(xmlSAXParseMemory(NULL, buffer, size, 0));
}
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
return(xmlSAXParseMemory(NULL, buffer, size, 1));
}
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
const char *buffer, int size) {
int ret = 0;
xmlParserCtxtPtr ctxt;
xmlSAXHandlerPtr oldsax = NULL;
if (sax == NULL) return -1;
ctxt = xmlCreateMemoryParserCtxt(buffer, size);
if (ctxt == NULL) return -1;
oldsax = ctxt->sax;
ctxt->sax = sax;
if (user_data != NULL)
ctxt->userData = user_data;
xmlParseDocument(ctxt);
if (ctxt->wellFormed)
ret = 0;
else {
if (ctxt->errNo != 0)
ret = ctxt->errNo;
else
ret = -1;
}
ctxt->sax = oldsax;
xmlFreeParserCtxt(ctxt);
return ret;
}
xmlParserCtxtPtr
xmlCreateDocParserCtxt(xmlChar *cur) {
int len;
if (cur == NULL)
return(NULL);
len = xmlStrlen(cur);
return(xmlCreateMemoryParserCtxt((char *)cur, len));
}
xmlDocPtr
xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
xmlDocPtr ret;
xmlParserCtxtPtr ctxt;
if (cur == NULL) return(NULL);
ctxt = xmlCreateDocParserCtxt(cur);
if (ctxt == NULL) return(NULL);
if (sax != NULL) {
ctxt->sax = sax;
ctxt->userData = NULL;
}
xmlParseDocument(ctxt);
if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
else {
ret = NULL;
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
}
if (sax != NULL)
ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return(ret);
}
xmlDocPtr
xmlParseDoc(xmlChar *cur) {
return(xmlSAXParseDoc(NULL, cur, 0));
}
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
static void
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
xmlNodePtr lastNode)
{
if (xmlEntityRefFunc != NULL) {
(*xmlEntityRefFunc) (ent, firstNode, lastNode);
}
}
void
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
{
xmlEntityRefFunc = func;
}
#ifdef LIBXML_XPATH_ENABLED
#include <libxml/xpath.h>
#endif
extern void xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
static int xmlParserInitialized = 0;
void
xmlInitParser(void) {
if (xmlParserInitialized != 0)
return;
if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
(xmlGenericError == NULL))
initGenericErrorDefaultFunc(NULL);
xmlInitThreads();
xmlInitMemory();
xmlInitCharEncodingHandlers();
xmlInitializePredefinedEntities();
xmlDefaultSAXHandlerInit();
xmlRegisterDefaultInputCallbacks();
xmlRegisterDefaultOutputCallbacks();
#ifdef LIBXML_HTML_ENABLED
htmlInitAutoClose();
htmlDefaultSAXHandlerInit();
#endif
#ifdef LIBXML_XPATH_ENABLED
xmlXPathInit();
#endif
xmlParserInitialized = 1;
}
void
xmlCleanupParser(void) {
xmlCleanupCharEncodingHandlers();
xmlCleanupPredefinedEntities();
#ifdef LIBXML_CATALOG_ENABLED
xmlCatalogCleanup();
#endif
xmlCleanupThreads();
xmlParserInitialized = 0;
}