Home | History | Annotate | Download | only in libxml2
      1 /*
      2  * xmlreader.c: implements the xmlTextReader streaming node API
      3  *
      4  * NOTE:
      5  *   XmlTextReader.Normalization Property won't be supported, since
      6  *     it makes the parser non compliant to the XML recommendation
      7  *
      8  * See Copyright for the status of this software.
      9  *
     10  * daniel (at) veillard.com
     11  */
     12 
     13 /*
     14  * TODOs:
     15  *   - XML Schemas validation
     16  */
     17 #define IN_LIBXML
     18 #include "libxml.h"
     19 
     20 #ifdef LIBXML_READER_ENABLED
     21 #include <string.h> /* for memset() only ! */
     22 #include <stdarg.h>
     23 
     24 #ifdef HAVE_CTYPE_H
     25 #include <ctype.h>
     26 #endif
     27 #ifdef HAVE_STDLIB_H
     28 #include <stdlib.h>
     29 #endif
     30 
     31 #include <libxml/xmlmemory.h>
     32 #include <libxml/xmlIO.h>
     33 #include <libxml/xmlreader.h>
     34 #include <libxml/parserInternals.h>
     35 #ifdef LIBXML_SCHEMAS_ENABLED
     36 #include <libxml/relaxng.h>
     37 #include <libxml/xmlschemas.h>
     38 #endif
     39 #include <libxml/uri.h>
     40 #ifdef LIBXML_XINCLUDE_ENABLED
     41 #include <libxml/xinclude.h>
     42 #endif
     43 #ifdef LIBXML_PATTERN_ENABLED
     44 #include <libxml/pattern.h>
     45 #endif
     46 
     47 #include "buf.h"
     48 
     49 #define MAX_ERR_MSG_SIZE 64000
     50 
     51 /*
     52  * The following VA_COPY was coded following an example in
     53  * the Samba project.  It may not be sufficient for some
     54  * esoteric implementations of va_list but (hopefully) will
     55  * be sufficient for libxml2.
     56  */
     57 #ifndef VA_COPY
     58   #ifdef HAVE_VA_COPY
     59     #define VA_COPY(dest, src) va_copy(dest, src)
     60   #else
     61     #ifdef HAVE___VA_COPY
     62       #define VA_COPY(dest,src) __va_copy(dest, src)
     63     #else
     64       #ifndef VA_LIST_IS_ARRAY
     65         #define VA_COPY(dest,src) (dest) = (src)
     66       #else
     67         #include <string.h>
     68         #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
     69       #endif
     70     #endif
     71   #endif
     72 #endif
     73 
     74 /* #define DEBUG_CALLBACKS */
     75 /* #define DEBUG_READER */
     76 
     77 /**
     78  * TODO:
     79  *
     80  * macro to flag unimplemented blocks
     81  */
     82 #define TODO								\
     83     xmlGenericError(xmlGenericErrorContext,				\
     84 	    "Unimplemented block at %s:%d\n",				\
     85             __FILE__, __LINE__);
     86 
     87 #ifdef DEBUG_READER
     88 #define DUMP_READER xmlTextReaderDebug(reader);
     89 #else
     90 #define DUMP_READER
     91 #endif
     92 
     93 #define CHUNK_SIZE 512
     94 /************************************************************************
     95  *									*
     96  *	The parser: maps the Text Reader API on top of the existing	*
     97  *		parsing routines building a tree			*
     98  *									*
     99  ************************************************************************/
    100 
    101 #define XML_TEXTREADER_INPUT	1
    102 #define XML_TEXTREADER_CTXT	2
    103 
    104 typedef enum {
    105     XML_TEXTREADER_NONE = -1,
    106     XML_TEXTREADER_START= 0,
    107     XML_TEXTREADER_ELEMENT= 1,
    108     XML_TEXTREADER_END= 2,
    109     XML_TEXTREADER_EMPTY= 3,
    110     XML_TEXTREADER_BACKTRACK= 4,
    111     XML_TEXTREADER_DONE= 5,
    112     XML_TEXTREADER_ERROR= 6
    113 } xmlTextReaderState;
    114 
    115 typedef enum {
    116     XML_TEXTREADER_NOT_VALIDATE = 0,
    117     XML_TEXTREADER_VALIDATE_DTD = 1,
    118     XML_TEXTREADER_VALIDATE_RNG = 2,
    119     XML_TEXTREADER_VALIDATE_XSD = 4
    120 } xmlTextReaderValidate;
    121 
    122 struct _xmlTextReader {
    123     int				mode;	/* the parsing mode */
    124     xmlDocPtr			doc;    /* when walking an existing doc */
    125     xmlTextReaderValidate       validate;/* is there any validation */
    126     int				allocs;	/* what structure were deallocated */
    127     xmlTextReaderState		state;
    128     xmlParserCtxtPtr		ctxt;	/* the parser context */
    129     xmlSAXHandlerPtr		sax;	/* the parser SAX callbacks */
    130     xmlParserInputBufferPtr	input;	/* the input */
    131     startElementSAXFunc		startElement;/* initial SAX callbacks */
    132     endElementSAXFunc		endElement;  /* idem */
    133     startElementNsSAX2Func	startElementNs;/* idem */
    134     endElementNsSAX2Func	endElementNs;  /* idem */
    135     charactersSAXFunc		characters;
    136     cdataBlockSAXFunc		cdataBlock;
    137     unsigned int		base;	/* base of the segment in the input */
    138     unsigned int		cur;	/* current position in the input */
    139     xmlNodePtr			node;	/* current node */
    140     xmlNodePtr			curnode;/* current attribute node */
    141     int				depth;  /* depth of the current node */
    142     xmlNodePtr			faketext;/* fake xmlNs chld */
    143     int				preserve;/* preserve the resulting document */
    144     xmlBufPtr		        buffer; /* used to return const xmlChar * */
    145     xmlDictPtr			dict;	/* the context dictionary */
    146 
    147     /* entity stack when traversing entities content */
    148     xmlNodePtr         ent;          /* Current Entity Ref Node */
    149     int                entNr;        /* Depth of the entities stack */
    150     int                entMax;       /* Max depth of the entities stack */
    151     xmlNodePtr        *entTab;       /* array of entities */
    152 
    153     /* error handling */
    154     xmlTextReaderErrorFunc errorFunc;    /* callback function */
    155     void                  *errorFuncArg; /* callback function user argument */
    156 
    157 #ifdef LIBXML_SCHEMAS_ENABLED
    158     /* Handling of RelaxNG validation */
    159     xmlRelaxNGPtr          rngSchemas;	/* The Relax NG schemas */
    160     xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
    161     int                    rngPreserveCtxt; /* 1 if the context was provided by the user */
    162     int                    rngValidErrors;/* The number of errors detected */
    163     xmlNodePtr             rngFullNode;	/* the node if RNG not progressive */
    164     /* Handling of Schemas validation */
    165     xmlSchemaPtr          xsdSchemas;	/* The Schemas schemas */
    166     xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
    167     int                   xsdPreserveCtxt; /* 1 if the context was provided by the user */
    168     int                   xsdValidErrors;/* The number of errors detected */
    169     xmlSchemaSAXPlugPtr   xsdPlug;	/* the schemas plug in SAX pipeline */
    170 #endif
    171 #ifdef LIBXML_XINCLUDE_ENABLED
    172     /* Handling of XInclude processing */
    173     int                xinclude;	/* is xinclude asked for */
    174     const xmlChar *    xinclude_name;	/* the xinclude name from dict */
    175     xmlXIncludeCtxtPtr xincctxt;	/* the xinclude context */
    176     int                in_xinclude;	/* counts for xinclude */
    177 #endif
    178 #ifdef LIBXML_PATTERN_ENABLED
    179     int                patternNr;       /* number of preserve patterns */
    180     int                patternMax;      /* max preserve patterns */
    181     xmlPatternPtr     *patternTab;      /* array of preserve patterns */
    182 #endif
    183     int                preserves;	/* level of preserves */
    184     int                parserFlags;	/* the set of options set */
    185     /* Structured error handling */
    186     xmlStructuredErrorFunc sErrorFunc;  /* callback function */
    187 };
    188 
    189 #define NODE_IS_EMPTY		0x1
    190 #define NODE_IS_PRESERVED	0x2
    191 #define NODE_IS_SPRESERVED	0x4
    192 
    193 /**
    194  * CONSTSTR:
    195  *
    196  * Macro used to return an interned string
    197  */
    198 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
    199 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
    200 
    201 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
    202 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
    203 
    204 /************************************************************************
    205  *									*
    206  *	Our own version of the freeing routines as we recycle nodes	*
    207  *									*
    208  ************************************************************************/
    209 /**
    210  * DICT_FREE:
    211  * @str:  a string
    212  *
    213  * Free a string if it is not owned by the "dict" dictionary in the
    214  * current scope
    215  */
    216 #define DICT_FREE(str)						\
    217 	if ((str) && ((!dict) ||				\
    218 	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
    219 	    xmlFree((char *)(str));
    220 
    221 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
    222 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
    223 
    224 /**
    225  * xmlFreeID:
    226  * @not:  A id
    227  *
    228  * Deallocate the memory used by an id definition
    229  */
    230 static void
    231 xmlFreeID(xmlIDPtr id) {
    232     xmlDictPtr dict = NULL;
    233 
    234     if (id == NULL) return;
    235 
    236     if (id->doc != NULL)
    237         dict = id->doc->dict;
    238 
    239     if (id->value != NULL)
    240 	DICT_FREE(id->value)
    241     xmlFree(id);
    242 }
    243 
    244 /**
    245  * xmlTextReaderRemoveID:
    246  * @doc:  the document
    247  * @attr:  the attribute
    248  *
    249  * Remove the given attribute from the ID table maintained internally.
    250  *
    251  * Returns -1 if the lookup failed and 0 otherwise
    252  */
    253 static int
    254 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
    255     xmlIDTablePtr table;
    256     xmlIDPtr id;
    257     xmlChar *ID;
    258 
    259     if (doc == NULL) return(-1);
    260     if (attr == NULL) return(-1);
    261     table = (xmlIDTablePtr) doc->ids;
    262     if (table == NULL)
    263         return(-1);
    264 
    265     ID = xmlNodeListGetString(doc, attr->children, 1);
    266     if (ID == NULL)
    267 	return(-1);
    268     id = xmlHashLookup(table, ID);
    269     xmlFree(ID);
    270     if (id == NULL || id->attr != attr) {
    271 	return(-1);
    272     }
    273     id->name = attr->name;
    274     id->attr = NULL;
    275     return(0);
    276 }
    277 
    278 /**
    279  * xmlTextReaderFreeProp:
    280  * @reader:  the xmlTextReaderPtr used
    281  * @cur:  the node
    282  *
    283  * Free a node.
    284  */
    285 static void
    286 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
    287     xmlDictPtr dict;
    288 
    289     if ((reader != NULL) && (reader->ctxt != NULL))
    290 	dict = reader->ctxt->dict;
    291     else
    292         dict = NULL;
    293     if (cur == NULL) return;
    294 
    295     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    296 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
    297 
    298     /* Check for ID removal -> leading to invalid references ! */
    299     if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
    300 	((cur->parent->doc->intSubset != NULL) ||
    301 	 (cur->parent->doc->extSubset != NULL))) {
    302         if (xmlIsID(cur->parent->doc, cur->parent, cur))
    303 	    xmlTextReaderRemoveID(cur->parent->doc, cur);
    304     }
    305     if (cur->children != NULL)
    306         xmlTextReaderFreeNodeList(reader, cur->children);
    307 
    308     DICT_FREE(cur->name);
    309     if ((reader != NULL) && (reader->ctxt != NULL) &&
    310         (reader->ctxt->freeAttrsNr < 100)) {
    311         cur->next = reader->ctxt->freeAttrs;
    312 	reader->ctxt->freeAttrs = cur;
    313 	reader->ctxt->freeAttrsNr++;
    314     } else {
    315 	xmlFree(cur);
    316     }
    317 }
    318 
    319 /**
    320  * xmlTextReaderFreePropList:
    321  * @reader:  the xmlTextReaderPtr used
    322  * @cur:  the first property in the list
    323  *
    324  * Free a property and all its siblings, all the children are freed too.
    325  */
    326 static void
    327 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
    328     xmlAttrPtr next;
    329 
    330     while (cur != NULL) {
    331         next = cur->next;
    332         xmlTextReaderFreeProp(reader, cur);
    333 	cur = next;
    334     }
    335 }
    336 
    337 /**
    338  * xmlTextReaderFreeNodeList:
    339  * @reader:  the xmlTextReaderPtr used
    340  * @cur:  the first node in the list
    341  *
    342  * Free a node and all its siblings, this is a recursive behaviour, all
    343  * the children are freed too.
    344  */
    345 static void
    346 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
    347     xmlNodePtr next;
    348     xmlDictPtr dict;
    349 
    350     if ((reader != NULL) && (reader->ctxt != NULL))
    351 	dict = reader->ctxt->dict;
    352     else
    353         dict = NULL;
    354     if (cur == NULL) return;
    355     if (cur->type == XML_NAMESPACE_DECL) {
    356 	xmlFreeNsList((xmlNsPtr) cur);
    357 	return;
    358     }
    359     if ((cur->type == XML_DOCUMENT_NODE) ||
    360 	(cur->type == XML_HTML_DOCUMENT_NODE)) {
    361 	xmlFreeDoc((xmlDocPtr) cur);
    362 	return;
    363     }
    364     while (cur != NULL) {
    365         next = cur->next;
    366 	/* unroll to speed up freeing the document */
    367 	if (cur->type != XML_DTD_NODE) {
    368 
    369 	    if ((cur->children != NULL) &&
    370 		(cur->type != XML_ENTITY_REF_NODE)) {
    371 		if (cur->children->parent == cur)
    372 		    xmlTextReaderFreeNodeList(reader, cur->children);
    373 		cur->children = NULL;
    374 	    }
    375 
    376 	    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    377 		xmlDeregisterNodeDefaultValue(cur);
    378 
    379 	    if (((cur->type == XML_ELEMENT_NODE) ||
    380 		 (cur->type == XML_XINCLUDE_START) ||
    381 		 (cur->type == XML_XINCLUDE_END)) &&
    382 		(cur->properties != NULL))
    383 		xmlTextReaderFreePropList(reader, cur->properties);
    384 	    if ((cur->content != (xmlChar *) &(cur->properties)) &&
    385 	        (cur->type != XML_ELEMENT_NODE) &&
    386 		(cur->type != XML_XINCLUDE_START) &&
    387 		(cur->type != XML_XINCLUDE_END) &&
    388 		(cur->type != XML_ENTITY_REF_NODE)) {
    389 		DICT_FREE(cur->content);
    390 	    }
    391 	    if (((cur->type == XML_ELEMENT_NODE) ||
    392 	         (cur->type == XML_XINCLUDE_START) ||
    393 		 (cur->type == XML_XINCLUDE_END)) &&
    394 		(cur->nsDef != NULL))
    395 		xmlFreeNsList(cur->nsDef);
    396 
    397 	    /*
    398 	     * we don't free element names here they are interned now
    399 	     */
    400 	    if ((cur->type != XML_TEXT_NODE) &&
    401 		(cur->type != XML_COMMENT_NODE))
    402 		DICT_FREE(cur->name);
    403 	    if (((cur->type == XML_ELEMENT_NODE) ||
    404 		 (cur->type == XML_TEXT_NODE)) &&
    405 	        (reader != NULL) && (reader->ctxt != NULL) &&
    406 		(reader->ctxt->freeElemsNr < 100)) {
    407 	        cur->next = reader->ctxt->freeElems;
    408 		reader->ctxt->freeElems = cur;
    409 		reader->ctxt->freeElemsNr++;
    410 	    } else {
    411 		xmlFree(cur);
    412 	    }
    413 	}
    414 	cur = next;
    415     }
    416 }
    417 
    418 /**
    419  * xmlTextReaderFreeNode:
    420  * @reader:  the xmlTextReaderPtr used
    421  * @cur:  the node
    422  *
    423  * Free a node, this is a recursive behaviour, all the children are freed too.
    424  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
    425  */
    426 static void
    427 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
    428     xmlDictPtr dict;
    429 
    430     if ((reader != NULL) && (reader->ctxt != NULL))
    431 	dict = reader->ctxt->dict;
    432     else
    433         dict = NULL;
    434     if (cur->type == XML_DTD_NODE) {
    435 	xmlFreeDtd((xmlDtdPtr) cur);
    436 	return;
    437     }
    438     if (cur->type == XML_NAMESPACE_DECL) {
    439 	xmlFreeNs((xmlNsPtr) cur);
    440         return;
    441     }
    442     if (cur->type == XML_ATTRIBUTE_NODE) {
    443 	xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
    444 	return;
    445     }
    446 
    447     if ((cur->children != NULL) &&
    448 	(cur->type != XML_ENTITY_REF_NODE)) {
    449 	if (cur->children->parent == cur)
    450 	    xmlTextReaderFreeNodeList(reader, cur->children);
    451 	cur->children = NULL;
    452     }
    453 
    454     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    455 	xmlDeregisterNodeDefaultValue(cur);
    456 
    457     if (((cur->type == XML_ELEMENT_NODE) ||
    458 	 (cur->type == XML_XINCLUDE_START) ||
    459 	 (cur->type == XML_XINCLUDE_END)) &&
    460 	(cur->properties != NULL))
    461 	xmlTextReaderFreePropList(reader, cur->properties);
    462     if ((cur->content != (xmlChar *) &(cur->properties)) &&
    463         (cur->type != XML_ELEMENT_NODE) &&
    464 	(cur->type != XML_XINCLUDE_START) &&
    465 	(cur->type != XML_XINCLUDE_END) &&
    466 	(cur->type != XML_ENTITY_REF_NODE)) {
    467 	DICT_FREE(cur->content);
    468     }
    469     if (((cur->type == XML_ELEMENT_NODE) ||
    470 	 (cur->type == XML_XINCLUDE_START) ||
    471 	 (cur->type == XML_XINCLUDE_END)) &&
    472 	(cur->nsDef != NULL))
    473 	xmlFreeNsList(cur->nsDef);
    474 
    475     /*
    476      * we don't free names here they are interned now
    477      */
    478     if ((cur->type != XML_TEXT_NODE) &&
    479         (cur->type != XML_COMMENT_NODE))
    480 	DICT_FREE(cur->name);
    481 
    482     if (((cur->type == XML_ELEMENT_NODE) ||
    483 	 (cur->type == XML_TEXT_NODE)) &&
    484 	(reader != NULL) && (reader->ctxt != NULL) &&
    485 	(reader->ctxt->freeElemsNr < 100)) {
    486 	cur->next = reader->ctxt->freeElems;
    487 	reader->ctxt->freeElems = cur;
    488 	reader->ctxt->freeElemsNr++;
    489     } else {
    490 	xmlFree(cur);
    491     }
    492 }
    493 
    494 static void
    495 xmlTextReaderFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
    496     xmlFreeID((xmlIDPtr) id);
    497 }
    498 
    499 /**
    500  * xmlTextReaderFreeIDTable:
    501  * @table:  An id table
    502  *
    503  * Deallocate the memory used by an ID hash table.
    504  */
    505 static void
    506 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
    507     xmlHashFree(table, xmlTextReaderFreeIDTableEntry);
    508 }
    509 
    510 /**
    511  * xmlTextReaderFreeDoc:
    512  * @reader:  the xmlTextReaderPtr used
    513  * @cur:  pointer to the document
    514  *
    515  * Free up all the structures used by a document, tree included.
    516  */
    517 static void
    518 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
    519     xmlDtdPtr extSubset, intSubset;
    520 
    521     if (cur == NULL) return;
    522 
    523     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    524 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
    525 
    526     /*
    527      * Do this before freeing the children list to avoid ID lookups
    528      */
    529     if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
    530     cur->ids = NULL;
    531     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
    532     cur->refs = NULL;
    533     extSubset = cur->extSubset;
    534     intSubset = cur->intSubset;
    535     if (intSubset == extSubset)
    536 	extSubset = NULL;
    537     if (extSubset != NULL) {
    538 	xmlUnlinkNode((xmlNodePtr) cur->extSubset);
    539 	cur->extSubset = NULL;
    540 	xmlFreeDtd(extSubset);
    541     }
    542     if (intSubset != NULL) {
    543 	xmlUnlinkNode((xmlNodePtr) cur->intSubset);
    544 	cur->intSubset = NULL;
    545 	xmlFreeDtd(intSubset);
    546     }
    547 
    548     if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
    549 
    550     if (cur->version != NULL) xmlFree((char *) cur->version);
    551     if (cur->name != NULL) xmlFree((char *) cur->name);
    552     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
    553     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
    554     if (cur->URL != NULL) xmlFree((char *) cur->URL);
    555     if (cur->dict != NULL) xmlDictFree(cur->dict);
    556 
    557     xmlFree(cur);
    558 }
    559 
    560 /************************************************************************
    561  *									*
    562  *			The reader core parser				*
    563  *									*
    564  ************************************************************************/
    565 #ifdef DEBUG_READER
    566 static void
    567 xmlTextReaderDebug(xmlTextReaderPtr reader) {
    568     if ((reader == NULL) || (reader->ctxt == NULL)) {
    569 	fprintf(stderr, "xmlTextReader NULL\n");
    570 	return;
    571     }
    572     fprintf(stderr, "xmlTextReader: state %d depth %d ",
    573 	    reader->state, reader->depth);
    574     if (reader->node == NULL) {
    575 	fprintf(stderr, "node = NULL\n");
    576     } else {
    577 	fprintf(stderr, "node %s\n", reader->node->name);
    578     }
    579     fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
    580 	    reader->base, reader->cur, reader->ctxt->nodeNr);
    581     if (reader->input->buffer == NULL) {
    582 	fprintf(stderr, "buffer is NULL\n");
    583     } else {
    584 #ifdef LIBXML_DEBUG_ENABLED
    585 	xmlDebugDumpString(stderr,
    586 		&reader->input->buffer->content[reader->cur]);
    587 #endif
    588 	fprintf(stderr, "\n");
    589     }
    590 }
    591 #endif
    592 
    593 /**
    594  * xmlTextReaderEntPush:
    595  * @reader:  the xmlTextReaderPtr used
    596  * @value:  the entity reference node
    597  *
    598  * Pushes a new entity reference node on top of the entities stack
    599  *
    600  * Returns 0 in case of error, the index in the stack otherwise
    601  */
    602 static int
    603 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
    604 {
    605     if (reader->entMax <= 0) {
    606 	reader->entMax = 10;
    607 	reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
    608 		                                  sizeof(reader->entTab[0]));
    609         if (reader->entTab == NULL) {
    610             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
    611             return (0);
    612         }
    613     }
    614     if (reader->entNr >= reader->entMax) {
    615         reader->entMax *= 2;
    616         reader->entTab =
    617             (xmlNodePtr *) xmlRealloc(reader->entTab,
    618                                       reader->entMax *
    619                                       sizeof(reader->entTab[0]));
    620         if (reader->entTab == NULL) {
    621             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
    622             return (0);
    623         }
    624     }
    625     reader->entTab[reader->entNr] = value;
    626     reader->ent = value;
    627     return (reader->entNr++);
    628 }
    629 
    630 /**
    631  * xmlTextReaderEntPop:
    632  * @reader:  the xmlTextReaderPtr used
    633  *
    634  * Pops the top element entity from the entities stack
    635  *
    636  * Returns the entity just removed
    637  */
    638 static xmlNodePtr
    639 xmlTextReaderEntPop(xmlTextReaderPtr reader)
    640 {
    641     xmlNodePtr ret;
    642 
    643     if (reader->entNr <= 0)
    644         return (NULL);
    645     reader->entNr--;
    646     if (reader->entNr > 0)
    647         reader->ent = reader->entTab[reader->entNr - 1];
    648     else
    649         reader->ent = NULL;
    650     ret = reader->entTab[reader->entNr];
    651     reader->entTab[reader->entNr] = NULL;
    652     return (ret);
    653 }
    654 
    655 /**
    656  * xmlTextReaderStartElement:
    657  * @ctx: the user data (XML parser context)
    658  * @fullname:  The element name, including namespace prefix
    659  * @atts:  An array of name/value attributes pairs, NULL terminated
    660  *
    661  * called when an opening tag has been processed.
    662  */
    663 static void
    664 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
    665 	                  const xmlChar **atts) {
    666     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    667     xmlTextReaderPtr reader = ctxt->_private;
    668 
    669 #ifdef DEBUG_CALLBACKS
    670     printf("xmlTextReaderStartElement(%s)\n", fullname);
    671 #endif
    672     if ((reader != NULL) && (reader->startElement != NULL)) {
    673 	reader->startElement(ctx, fullname, atts);
    674 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
    675 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
    676 	    (ctxt->input->cur[1] == '>'))
    677 	    ctxt->node->extra = NODE_IS_EMPTY;
    678     }
    679     if (reader != NULL)
    680 	reader->state = XML_TEXTREADER_ELEMENT;
    681 }
    682 
    683 /**
    684  * xmlTextReaderEndElement:
    685  * @ctx: the user data (XML parser context)
    686  * @fullname:  The element name, including namespace prefix
    687  *
    688  * called when an ending tag has been processed.
    689  */
    690 static void
    691 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
    692     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    693     xmlTextReaderPtr reader = ctxt->_private;
    694 
    695 #ifdef DEBUG_CALLBACKS
    696     printf("xmlTextReaderEndElement(%s)\n", fullname);
    697 #endif
    698     if ((reader != NULL) && (reader->endElement != NULL)) {
    699 	reader->endElement(ctx, fullname);
    700     }
    701 }
    702 
    703 /**
    704  * xmlTextReaderStartElementNs:
    705  * @ctx: the user data (XML parser context)
    706  * @localname:  the local name of the element
    707  * @prefix:  the element namespace prefix if available
    708  * @URI:  the element namespace name if available
    709  * @nb_namespaces:  number of namespace definitions on that node
    710  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
    711  * @nb_attributes:  the number of attributes on that node
    712  * nb_defaulted:  the number of defaulted attributes.
    713  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
    714  *               attribute values.
    715  *
    716  * called when an opening tag has been processed.
    717  */
    718 static void
    719 xmlTextReaderStartElementNs(void *ctx,
    720                       const xmlChar *localname,
    721 		      const xmlChar *prefix,
    722 		      const xmlChar *URI,
    723 		      int nb_namespaces,
    724 		      const xmlChar **namespaces,
    725 		      int nb_attributes,
    726 		      int nb_defaulted,
    727 		      const xmlChar **attributes)
    728 {
    729     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    730     xmlTextReaderPtr reader = ctxt->_private;
    731 
    732 #ifdef DEBUG_CALLBACKS
    733     printf("xmlTextReaderStartElementNs(%s)\n", localname);
    734 #endif
    735     if ((reader != NULL) && (reader->startElementNs != NULL)) {
    736 	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
    737 	                       namespaces, nb_attributes, nb_defaulted,
    738 			       attributes);
    739 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
    740 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
    741 	    (ctxt->input->cur[1] == '>'))
    742 	    ctxt->node->extra = NODE_IS_EMPTY;
    743     }
    744     if (reader != NULL)
    745 	reader->state = XML_TEXTREADER_ELEMENT;
    746 }
    747 
    748 /**
    749  * xmlTextReaderEndElementNs:
    750  * @ctx: the user data (XML parser context)
    751  * @localname:  the local name of the element
    752  * @prefix:  the element namespace prefix if available
    753  * @URI:  the element namespace name if available
    754  *
    755  * called when an ending tag has been processed.
    756  */
    757 static void
    758 xmlTextReaderEndElementNs(void *ctx,
    759                           const xmlChar * localname,
    760                           const xmlChar * prefix,
    761 		          const xmlChar * URI)
    762 {
    763     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    764     xmlTextReaderPtr reader = ctxt->_private;
    765 
    766 #ifdef DEBUG_CALLBACKS
    767     printf("xmlTextReaderEndElementNs(%s)\n", localname);
    768 #endif
    769     if ((reader != NULL) && (reader->endElementNs != NULL)) {
    770 	reader->endElementNs(ctx, localname, prefix, URI);
    771     }
    772 }
    773 
    774 
    775 /**
    776  * xmlTextReaderCharacters:
    777  * @ctx: the user data (XML parser context)
    778  * @ch:  a xmlChar string
    779  * @len: the number of xmlChar
    780  *
    781  * receiving some chars from the parser.
    782  */
    783 static void
    784 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
    785 {
    786     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    787     xmlTextReaderPtr reader = ctxt->_private;
    788 
    789 #ifdef DEBUG_CALLBACKS
    790     printf("xmlTextReaderCharacters()\n");
    791 #endif
    792     if ((reader != NULL) && (reader->characters != NULL)) {
    793 	reader->characters(ctx, ch, len);
    794     }
    795 }
    796 
    797 /**
    798  * xmlTextReaderCDataBlock:
    799  * @ctx: the user data (XML parser context)
    800  * @value:  The pcdata content
    801  * @len:  the block length
    802  *
    803  * called when a pcdata block has been parsed
    804  */
    805 static void
    806 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
    807 {
    808     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    809     xmlTextReaderPtr reader = ctxt->_private;
    810 
    811 #ifdef DEBUG_CALLBACKS
    812     printf("xmlTextReaderCDataBlock()\n");
    813 #endif
    814     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
    815 	reader->cdataBlock(ctx, ch, len);
    816     }
    817 }
    818 
    819 /**
    820  * xmlTextReaderPushData:
    821  * @reader:  the xmlTextReaderPtr used
    822  *
    823  * Push data down the progressive parser until a significant callback
    824  * got raised.
    825  *
    826  * Returns -1 in case of failure, 0 otherwise
    827  */
    828 static int
    829 xmlTextReaderPushData(xmlTextReaderPtr reader) {
    830     xmlBufPtr inbuf;
    831     int val, s;
    832     xmlTextReaderState oldstate;
    833     int alloc;
    834 
    835     if ((reader->input == NULL) || (reader->input->buffer == NULL))
    836 	return(-1);
    837 
    838     oldstate = reader->state;
    839     reader->state = XML_TEXTREADER_NONE;
    840     inbuf = reader->input->buffer;
    841     alloc = xmlBufGetAllocationScheme(inbuf);
    842 
    843     while (reader->state == XML_TEXTREADER_NONE) {
    844 	if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
    845 	    /*
    846 	     * Refill the buffer unless we are at the end of the stream
    847 	     */
    848 	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
    849 		val = xmlParserInputBufferRead(reader->input, 4096);
    850 		if ((val == 0) &&
    851 		    (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
    852 		    if (xmlBufUse(inbuf) == reader->cur) {
    853 			reader->mode = XML_TEXTREADER_MODE_EOF;
    854 			reader->state = oldstate;
    855 		    }
    856 		} else if (val < 0) {
    857 		    reader->mode = XML_TEXTREADER_MODE_EOF;
    858 		    reader->state = oldstate;
    859 		    if ((oldstate != XML_TEXTREADER_START) ||
    860 			(reader->ctxt->myDoc != NULL))
    861 			return(val);
    862 		} else if (val == 0) {
    863 		    /* mark the end of the stream and process the remains */
    864 		    reader->mode = XML_TEXTREADER_MODE_EOF;
    865 		    break;
    866 		}
    867 
    868 	    } else
    869 		break;
    870 	}
    871 	/*
    872 	 * parse by block of CHUNK_SIZE bytes, various tests show that
    873 	 * it's the best tradeoff at least on a 1.2GH Duron
    874 	 */
    875 	if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
    876 	    val = xmlParseChunk(reader->ctxt,
    877                  (const char *) xmlBufContent(inbuf) + reader->cur,
    878                                 CHUNK_SIZE, 0);
    879 	    reader->cur += CHUNK_SIZE;
    880 	    if (val != 0)
    881 		reader->ctxt->wellFormed = 0;
    882 	    if (reader->ctxt->wellFormed == 0)
    883 		break;
    884 	} else {
    885 	    s = xmlBufUse(inbuf) - reader->cur;
    886 	    val = xmlParseChunk(reader->ctxt,
    887 		 (const char *) xmlBufContent(inbuf) + reader->cur,
    888 			        s, 0);
    889 	    reader->cur += s;
    890 	    if (val != 0)
    891 		reader->ctxt->wellFormed = 0;
    892 	    break;
    893 	}
    894     }
    895 
    896     /*
    897      * Discard the consumed input when needed and possible
    898      */
    899     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
    900         if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
    901 	    if ((reader->cur >= 4096) &&
    902 		(xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
    903 		val = xmlBufShrink(inbuf, reader->cur);
    904 		if (val >= 0) {
    905 		    reader->cur -= val;
    906 		}
    907 	    }
    908 	}
    909     }
    910 
    911     /*
    912      * At the end of the stream signal that the work is done to the Push
    913      * parser.
    914      */
    915     else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
    916 	if (reader->state != XML_TEXTREADER_DONE) {
    917 	    s = xmlBufUse(inbuf) - reader->cur;
    918 	    val = xmlParseChunk(reader->ctxt,
    919 		 (const char *) xmlBufContent(inbuf) + reader->cur,
    920 			        s, 1);
    921 	    reader->cur = xmlBufUse(inbuf);
    922 	    reader->state  = XML_TEXTREADER_DONE;
    923 	    if (val != 0) {
    924 	        if (reader->ctxt->wellFormed)
    925 		    reader->ctxt->wellFormed = 0;
    926 		else
    927 		    return(-1);
    928 	    }
    929 	}
    930     }
    931     reader->state = oldstate;
    932     if (reader->ctxt->wellFormed == 0) {
    933 	reader->mode = XML_TEXTREADER_MODE_EOF;
    934         return(-1);
    935     }
    936 
    937     return(0);
    938 }
    939 
    940 #ifdef LIBXML_REGEXP_ENABLED
    941 /**
    942  * xmlTextReaderValidatePush:
    943  * @reader:  the xmlTextReaderPtr used
    944  *
    945  * Push the current node for validation
    946  */
    947 static void
    948 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
    949     xmlNodePtr node = reader->node;
    950 
    951 #ifdef LIBXML_VALID_ENABLED
    952     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
    953         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
    954 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
    955 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
    956 				    reader->ctxt->myDoc, node, node->name);
    957 	} else {
    958 	    /* TODO use the BuildQName interface */
    959 	    xmlChar *qname;
    960 
    961 	    qname = xmlStrdup(node->ns->prefix);
    962 	    qname = xmlStrcat(qname, BAD_CAST ":");
    963 	    qname = xmlStrcat(qname, node->name);
    964 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
    965 				    reader->ctxt->myDoc, node, qname);
    966 	    if (qname != NULL)
    967 		xmlFree(qname);
    968 	}
    969     }
    970 #endif /* LIBXML_VALID_ENABLED */
    971 #ifdef LIBXML_SCHEMAS_ENABLED
    972     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
    973                (reader->rngValidCtxt != NULL)) {
    974 	int ret;
    975 
    976 	if (reader->rngFullNode != NULL) return;
    977 	ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
    978 	                                    reader->ctxt->myDoc,
    979 					    node);
    980 	if (ret == 0) {
    981 	    /*
    982 	     * this element requires a full tree
    983 	     */
    984 	    node = xmlTextReaderExpand(reader);
    985 	    if (node == NULL) {
    986 printf("Expand failed !\n");
    987 	        ret = -1;
    988 	    } else {
    989 		ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
    990 						    reader->ctxt->myDoc,
    991 						    node);
    992 		reader->rngFullNode = node;
    993 	    }
    994 	}
    995 	if (ret != 1)
    996 	    reader->rngValidErrors++;
    997     }
    998 #endif
    999 }
   1000 
   1001 /**
   1002  * xmlTextReaderValidateCData:
   1003  * @reader:  the xmlTextReaderPtr used
   1004  * @data:  pointer to the CData
   1005  * @len:  length of the CData block in bytes.
   1006  *
   1007  * Push some CData for validation
   1008  */
   1009 static void
   1010 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
   1011                            const xmlChar *data, int len) {
   1012 #ifdef LIBXML_VALID_ENABLED
   1013     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
   1014         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
   1015 	reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
   1016 	                                            data, len);
   1017     }
   1018 #endif /* LIBXML_VALID_ENABLED */
   1019 #ifdef LIBXML_SCHEMAS_ENABLED
   1020     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
   1021                (reader->rngValidCtxt != NULL)) {
   1022 	int ret;
   1023 
   1024 	if (reader->rngFullNode != NULL) return;
   1025 	ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
   1026 	if (ret != 1)
   1027 	    reader->rngValidErrors++;
   1028     }
   1029 #endif
   1030 }
   1031 
   1032 /**
   1033  * xmlTextReaderValidatePop:
   1034  * @reader:  the xmlTextReaderPtr used
   1035  *
   1036  * Pop the current node from validation
   1037  */
   1038 static void
   1039 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
   1040     xmlNodePtr node = reader->node;
   1041 
   1042 #ifdef LIBXML_VALID_ENABLED
   1043     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
   1044         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
   1045 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
   1046 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
   1047 				    reader->ctxt->myDoc, node, node->name);
   1048 	} else {
   1049 	    /* TODO use the BuildQName interface */
   1050 	    xmlChar *qname;
   1051 
   1052 	    qname = xmlStrdup(node->ns->prefix);
   1053 	    qname = xmlStrcat(qname, BAD_CAST ":");
   1054 	    qname = xmlStrcat(qname, node->name);
   1055 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
   1056 				    reader->ctxt->myDoc, node, qname);
   1057 	    if (qname != NULL)
   1058 		xmlFree(qname);
   1059 	}
   1060     }
   1061 #endif /* LIBXML_VALID_ENABLED */
   1062 #ifdef LIBXML_SCHEMAS_ENABLED
   1063     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
   1064                (reader->rngValidCtxt != NULL)) {
   1065 	int ret;
   1066 
   1067 	if (reader->rngFullNode != NULL) {
   1068 	    if (node == reader->rngFullNode)
   1069 	        reader->rngFullNode = NULL;
   1070 	    return;
   1071 	}
   1072 	ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
   1073 	                                   reader->ctxt->myDoc,
   1074 					   node);
   1075 	if (ret != 1)
   1076 	    reader->rngValidErrors++;
   1077     }
   1078 #endif
   1079 }
   1080 
   1081 /**
   1082  * xmlTextReaderValidateEntity:
   1083  * @reader:  the xmlTextReaderPtr used
   1084  *
   1085  * Handle the validation when an entity reference is encountered and
   1086  * entity substitution is not activated. As a result the parser interface
   1087  * must walk through the entity and do the validation calls
   1088  */
   1089 static void
   1090 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
   1091     xmlNodePtr oldnode = reader->node;
   1092     xmlNodePtr node = reader->node;
   1093     xmlParserCtxtPtr ctxt = reader->ctxt;
   1094 
   1095     do {
   1096 	if (node->type == XML_ENTITY_REF_NODE) {
   1097 	    /*
   1098 	     * Case where the underlying tree is not availble, lookup the entity
   1099 	     * and walk it.
   1100 	     */
   1101 	    if ((node->children == NULL) && (ctxt->sax != NULL) &&
   1102 		(ctxt->sax->getEntity != NULL)) {
   1103 		node->children = (xmlNodePtr)
   1104 		    ctxt->sax->getEntity(ctxt, node->name);
   1105 	    }
   1106 
   1107 	    if ((node->children != NULL) &&
   1108 		(node->children->type == XML_ENTITY_DECL) &&
   1109 		(node->children->children != NULL)) {
   1110 		xmlTextReaderEntPush(reader, node);
   1111 		node = node->children->children;
   1112 		continue;
   1113 	    } else {
   1114 		/*
   1115 		 * The error has probably be raised already.
   1116 		 */
   1117 		if (node == oldnode)
   1118 		    break;
   1119 		node = node->next;
   1120 	    }
   1121 #ifdef LIBXML_REGEXP_ENABLED
   1122 	} else if (node->type == XML_ELEMENT_NODE) {
   1123 	    reader->node = node;
   1124 	    xmlTextReaderValidatePush(reader);
   1125 	} else if ((node->type == XML_TEXT_NODE) ||
   1126 		   (node->type == XML_CDATA_SECTION_NODE)) {
   1127             xmlTextReaderValidateCData(reader, node->content,
   1128 	                               xmlStrlen(node->content));
   1129 #endif
   1130 	}
   1131 
   1132 	/*
   1133 	 * go to next node
   1134 	 */
   1135 	if (node->children != NULL) {
   1136 	    node = node->children;
   1137 	    continue;
   1138 	} else if (node->type == XML_ELEMENT_NODE) {
   1139 	    xmlTextReaderValidatePop(reader);
   1140 	}
   1141 	if (node->next != NULL) {
   1142 	    node = node->next;
   1143 	    continue;
   1144 	}
   1145 	do {
   1146 	    node = node->parent;
   1147 	    if (node->type == XML_ELEMENT_NODE) {
   1148 	        xmlNodePtr tmp;
   1149 		if (reader->entNr == 0) {
   1150 		    while ((tmp = node->last) != NULL) {
   1151 			if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
   1152 			    xmlUnlinkNode(tmp);
   1153 			    xmlTextReaderFreeNode(reader, tmp);
   1154 			} else
   1155 			    break;
   1156 		    }
   1157 		}
   1158 		reader->node = node;
   1159 		xmlTextReaderValidatePop(reader);
   1160 	    }
   1161 	    if ((node->type == XML_ENTITY_DECL) &&
   1162 		(reader->ent != NULL) && (reader->ent->children == node)) {
   1163 		node = xmlTextReaderEntPop(reader);
   1164 	    }
   1165 	    if (node == oldnode)
   1166 		break;
   1167 	    if (node->next != NULL) {
   1168 		node = node->next;
   1169 		break;
   1170 	    }
   1171 	} while ((node != NULL) && (node != oldnode));
   1172     } while ((node != NULL) && (node != oldnode));
   1173     reader->node = oldnode;
   1174 }
   1175 #endif /* LIBXML_REGEXP_ENABLED */
   1176 
   1177 
   1178 /**
   1179  * xmlTextReaderGetSuccessor:
   1180  * @cur:  the current node
   1181  *
   1182  * Get the successor of a node if available.
   1183  *
   1184  * Returns the successor node or NULL
   1185  */
   1186 static xmlNodePtr
   1187 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
   1188     if (cur == NULL) return(NULL) ; /* ERROR */
   1189     if (cur->next != NULL) return(cur->next) ;
   1190     do {
   1191         cur = cur->parent;
   1192         if (cur == NULL) break;
   1193         if (cur->next != NULL) return(cur->next);
   1194     } while (cur != NULL);
   1195     return(cur);
   1196 }
   1197 
   1198 /**
   1199  * xmlTextReaderDoExpand:
   1200  * @reader:  the xmlTextReaderPtr used
   1201  *
   1202  * Makes sure that the current node is fully read as well as all its
   1203  * descendant. It means the full DOM subtree must be available at the
   1204  * end of the call.
   1205  *
   1206  * Returns 1 if the node was expanded successfully, 0 if there is no more
   1207  *          nodes to read, or -1 in case of error
   1208  */
   1209 static int
   1210 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
   1211     int val;
   1212 
   1213     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
   1214         return(-1);
   1215     do {
   1216 	if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
   1217 
   1218         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
   1219 	    return(1);
   1220 	if (reader->ctxt->nodeNr < reader->depth)
   1221 	    return(1);
   1222 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
   1223 	    return(1);
   1224 	val = xmlTextReaderPushData(reader);
   1225 	if (val < 0){
   1226 	    reader->mode = XML_TEXTREADER_MODE_ERROR;
   1227 	    return(-1);
   1228 	}
   1229     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
   1230     return(1);
   1231 }
   1232 
   1233 /**
   1234  * xmlTextReaderCollectSiblings:
   1235  * @node:    the first child
   1236  *
   1237  *  Traverse depth-first through all sibling nodes and their children
   1238  *  nodes and concatenate their content. This is an auxiliary function
   1239  *  to xmlTextReaderReadString.
   1240  *
   1241  *  Returns a string containing the content, or NULL in case of error.
   1242  */
   1243 static xmlChar *
   1244 xmlTextReaderCollectSiblings(xmlNodePtr node)
   1245 {
   1246     xmlBufferPtr buffer;
   1247     xmlChar *ret;
   1248 
   1249     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
   1250         return(NULL);
   1251 
   1252     buffer = xmlBufferCreate();
   1253     if (buffer == NULL)
   1254        return NULL;
   1255 
   1256     for ( ; node != NULL; node = node->next) {
   1257        switch (node->type) {
   1258        case XML_TEXT_NODE:
   1259        case XML_CDATA_SECTION_NODE:
   1260            xmlBufferCat(buffer, node->content);
   1261            break;
   1262        case XML_ELEMENT_NODE: {
   1263            xmlChar *tmp;
   1264 
   1265 	   tmp = xmlTextReaderCollectSiblings(node->children);
   1266            xmlBufferCat(buffer, tmp);
   1267 	   xmlFree(tmp);
   1268 	   break;
   1269        }
   1270        default:
   1271            break;
   1272        }
   1273     }
   1274     ret = buffer->content;
   1275     buffer->content = NULL;
   1276     xmlBufferFree(buffer);
   1277     return(ret);
   1278 }
   1279 
   1280 /**
   1281  * xmlTextReaderRead:
   1282  * @reader:  the xmlTextReaderPtr used
   1283  *
   1284  *  Moves the position of the current instance to the next node in
   1285  *  the stream, exposing its properties.
   1286  *
   1287  *  Returns 1 if the node was read successfully, 0 if there is no more
   1288  *          nodes to read, or -1 in case of error
   1289  */
   1290 int
   1291 xmlTextReaderRead(xmlTextReaderPtr reader) {
   1292     int val, olddepth = 0;
   1293     xmlTextReaderState oldstate = XML_TEXTREADER_START;
   1294     xmlNodePtr oldnode = NULL;
   1295 
   1296 
   1297     if (reader == NULL)
   1298 	return(-1);
   1299     reader->curnode = NULL;
   1300     if (reader->doc != NULL)
   1301         return(xmlTextReaderReadTree(reader));
   1302     if (reader->ctxt == NULL)
   1303 	return(-1);
   1304 
   1305 #ifdef DEBUG_READER
   1306     fprintf(stderr, "\nREAD ");
   1307     DUMP_READER
   1308 #endif
   1309     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
   1310 	reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
   1311 	/*
   1312 	 * Initial state
   1313 	 */
   1314 	do {
   1315 	    val = xmlTextReaderPushData(reader);
   1316 		if (val < 0){
   1317 			reader->mode = XML_TEXTREADER_MODE_ERROR;
   1318 			reader->state = XML_TEXTREADER_ERROR;
   1319 		return(-1);
   1320 		}
   1321 	} while ((reader->ctxt->node == NULL) &&
   1322 		 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
   1323 		  (reader->state != XML_TEXTREADER_DONE)));
   1324 	if (reader->ctxt->node == NULL) {
   1325 	    if (reader->ctxt->myDoc != NULL) {
   1326 		reader->node = reader->ctxt->myDoc->children;
   1327 	    }
   1328 	    if (reader->node == NULL){
   1329 			reader->mode = XML_TEXTREADER_MODE_ERROR;
   1330 			reader->state = XML_TEXTREADER_ERROR;
   1331 		return(-1);
   1332 		}
   1333 	    reader->state = XML_TEXTREADER_ELEMENT;
   1334 	} else {
   1335 	    if (reader->ctxt->myDoc != NULL) {
   1336 		reader->node = reader->ctxt->myDoc->children;
   1337 	    }
   1338 	    if (reader->node == NULL)
   1339 		reader->node = reader->ctxt->nodeTab[0];
   1340 	    reader->state = XML_TEXTREADER_ELEMENT;
   1341 	}
   1342 	reader->depth = 0;
   1343 	reader->ctxt->parseMode = XML_PARSE_READER;
   1344 	goto node_found;
   1345     }
   1346     oldstate = reader->state;
   1347     olddepth = reader->ctxt->nodeNr;
   1348     oldnode = reader->node;
   1349 
   1350 get_next_node:
   1351     if (reader->node == NULL) {
   1352 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
   1353 	    return(0);
   1354 	else
   1355 	    return(-1);
   1356     }
   1357 
   1358     /*
   1359      * If we are not backtracking on ancestors or examined nodes,
   1360      * that the parser didn't finished or that we arent at the end
   1361      * of stream, continue processing.
   1362      */
   1363     while ((reader->node != NULL) && (reader->node->next == NULL) &&
   1364 	   (reader->ctxt->nodeNr == olddepth) &&
   1365            ((oldstate == XML_TEXTREADER_BACKTRACK) ||
   1366             (reader->node->children == NULL) ||
   1367 	    (reader->node->type == XML_ENTITY_REF_NODE) ||
   1368 	    ((reader->node->children != NULL) &&
   1369 	     (reader->node->children->type == XML_TEXT_NODE) &&
   1370 	     (reader->node->children->next == NULL)) ||
   1371 	    (reader->node->type == XML_DTD_NODE) ||
   1372 	    (reader->node->type == XML_DOCUMENT_NODE) ||
   1373 	    (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
   1374 	   ((reader->ctxt->node == NULL) ||
   1375 	    (reader->ctxt->node == reader->node) ||
   1376 	    (reader->ctxt->node == reader->node->parent)) &&
   1377 	   (reader->ctxt->instate != XML_PARSER_EOF)) {
   1378 	val = xmlTextReaderPushData(reader);
   1379 	if (val < 0){
   1380 		reader->mode = XML_TEXTREADER_MODE_ERROR;
   1381 		reader->state = XML_TEXTREADER_ERROR;
   1382 	    return(-1);
   1383 	}
   1384 	if (reader->node == NULL)
   1385 	    goto node_end;
   1386     }
   1387     if (oldstate != XML_TEXTREADER_BACKTRACK) {
   1388 	if ((reader->node->children != NULL) &&
   1389 	    (reader->node->type != XML_ENTITY_REF_NODE) &&
   1390 	    (reader->node->type != XML_XINCLUDE_START) &&
   1391 	    (reader->node->type != XML_DTD_NODE)) {
   1392 	    reader->node = reader->node->children;
   1393 	    reader->depth++;
   1394 	    reader->state = XML_TEXTREADER_ELEMENT;
   1395 	    goto node_found;
   1396 	}
   1397     }
   1398     if (reader->node->next != NULL) {
   1399 	if ((oldstate == XML_TEXTREADER_ELEMENT) &&
   1400             (reader->node->type == XML_ELEMENT_NODE) &&
   1401 	    (reader->node->children == NULL) &&
   1402 	    ((reader->node->extra & NODE_IS_EMPTY) == 0)
   1403 #ifdef LIBXML_XINCLUDE_ENABLED
   1404 	    && (reader->in_xinclude <= 0)
   1405 #endif
   1406 	    ) {
   1407 	    reader->state = XML_TEXTREADER_END;
   1408 	    goto node_found;
   1409 	}
   1410 #ifdef LIBXML_REGEXP_ENABLED
   1411 	if ((reader->validate) &&
   1412 	    (reader->node->type == XML_ELEMENT_NODE))
   1413 	    xmlTextReaderValidatePop(reader);
   1414 #endif /* LIBXML_REGEXP_ENABLED */
   1415         if ((reader->preserves > 0) &&
   1416 	    (reader->node->extra & NODE_IS_SPRESERVED))
   1417 	    reader->preserves--;
   1418 	reader->node = reader->node->next;
   1419 	reader->state = XML_TEXTREADER_ELEMENT;
   1420 
   1421 	/*
   1422 	 * Cleanup of the old node
   1423 	 */
   1424 	if ((reader->preserves == 0) &&
   1425 #ifdef LIBXML_XINCLUDE_ENABLED
   1426 	    (reader->in_xinclude == 0) &&
   1427 #endif
   1428 	    (reader->entNr == 0) &&
   1429 	    (reader->node->prev != NULL) &&
   1430             (reader->node->prev->type != XML_DTD_NODE)) {
   1431 	    xmlNodePtr tmp = reader->node->prev;
   1432 	    if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
   1433 		xmlUnlinkNode(tmp);
   1434 		xmlTextReaderFreeNode(reader, tmp);
   1435 	    }
   1436 	}
   1437 
   1438 	goto node_found;
   1439     }
   1440     if ((oldstate == XML_TEXTREADER_ELEMENT) &&
   1441 	(reader->node->type == XML_ELEMENT_NODE) &&
   1442 	(reader->node->children == NULL) &&
   1443 	((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
   1444 	reader->state = XML_TEXTREADER_END;
   1445 	goto node_found;
   1446     }
   1447 #ifdef LIBXML_REGEXP_ENABLED
   1448     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
   1449 	xmlTextReaderValidatePop(reader);
   1450 #endif /* LIBXML_REGEXP_ENABLED */
   1451     if ((reader->preserves > 0) &&
   1452 	(reader->node->extra & NODE_IS_SPRESERVED))
   1453 	reader->preserves--;
   1454     reader->node = reader->node->parent;
   1455     if ((reader->node == NULL) ||
   1456 	(reader->node->type == XML_DOCUMENT_NODE) ||
   1457 #ifdef LIBXML_DOCB_ENABLED
   1458 	(reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
   1459 #endif
   1460 	(reader->node->type == XML_HTML_DOCUMENT_NODE)) {
   1461 	if (reader->mode != XML_TEXTREADER_MODE_EOF) {
   1462 	    val = xmlParseChunk(reader->ctxt, "", 0, 1);
   1463 	    reader->state = XML_TEXTREADER_DONE;
   1464 	    if (val != 0)
   1465 	        return(-1);
   1466 	}
   1467 	reader->node = NULL;
   1468 	reader->depth = -1;
   1469 
   1470 	/*
   1471 	 * Cleanup of the old node
   1472 	 */
   1473 	if ((oldnode != NULL) && (reader->preserves == 0) &&
   1474 #ifdef LIBXML_XINCLUDE_ENABLED
   1475 	    (reader->in_xinclude == 0) &&
   1476 #endif
   1477 	    (reader->entNr == 0) &&
   1478 	    (oldnode->type != XML_DTD_NODE) &&
   1479 	    ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
   1480 	    xmlUnlinkNode(oldnode);
   1481 	    xmlTextReaderFreeNode(reader, oldnode);
   1482 	}
   1483 
   1484 	goto node_end;
   1485     }
   1486     if ((reader->preserves == 0) &&
   1487 #ifdef LIBXML_XINCLUDE_ENABLED
   1488         (reader->in_xinclude == 0) &&
   1489 #endif
   1490 	(reader->entNr == 0) &&
   1491         (reader->node->last != NULL) &&
   1492         ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
   1493 	xmlNodePtr tmp = reader->node->last;
   1494 	xmlUnlinkNode(tmp);
   1495 	xmlTextReaderFreeNode(reader, tmp);
   1496     }
   1497     reader->depth--;
   1498     reader->state = XML_TEXTREADER_BACKTRACK;
   1499 
   1500 node_found:
   1501     DUMP_READER
   1502 
   1503     /*
   1504      * If we are in the middle of a piece of CDATA make sure it's finished
   1505      */
   1506     if ((reader->node != NULL) &&
   1507         (reader->node->next == NULL) &&
   1508         ((reader->node->type == XML_TEXT_NODE) ||
   1509 	 (reader->node->type == XML_CDATA_SECTION_NODE))) {
   1510             if (xmlTextReaderExpand(reader) == NULL)
   1511 	        return -1;
   1512     }
   1513 
   1514 #ifdef LIBXML_XINCLUDE_ENABLED
   1515     /*
   1516      * Handle XInclude if asked for
   1517      */
   1518     if ((reader->xinclude) && (reader->node != NULL) &&
   1519 	(reader->node->type == XML_ELEMENT_NODE) &&
   1520 	(reader->node->ns != NULL) &&
   1521 	((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
   1522 	 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
   1523 	if (reader->xincctxt == NULL) {
   1524 	    reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
   1525 	    xmlXIncludeSetFlags(reader->xincctxt,
   1526 	                        reader->parserFlags & (~XML_PARSE_NOXINCNODE));
   1527 	}
   1528 	/*
   1529 	 * expand that node and process it
   1530 	 */
   1531 	if (xmlTextReaderExpand(reader) == NULL)
   1532 	    return -1;
   1533 	xmlXIncludeProcessNode(reader->xincctxt, reader->node);
   1534     }
   1535     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
   1536         reader->in_xinclude++;
   1537 	goto get_next_node;
   1538     }
   1539     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
   1540         reader->in_xinclude--;
   1541 	goto get_next_node;
   1542     }
   1543 #endif
   1544     /*
   1545      * Handle entities enter and exit when in entity replacement mode
   1546      */
   1547     if ((reader->node != NULL) &&
   1548 	(reader->node->type == XML_ENTITY_REF_NODE) &&
   1549 	(reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
   1550 	/*
   1551 	 * Case where the underlying tree is not availble, lookup the entity
   1552 	 * and walk it.
   1553 	 */
   1554 	if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
   1555 	    (reader->ctxt->sax->getEntity != NULL)) {
   1556 	    reader->node->children = (xmlNodePtr)
   1557 		reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
   1558 	}
   1559 
   1560 	if ((reader->node->children != NULL) &&
   1561 	    (reader->node->children->type == XML_ENTITY_DECL) &&
   1562 	    (reader->node->children->children != NULL)) {
   1563 	    xmlTextReaderEntPush(reader, reader->node);
   1564 	    reader->node = reader->node->children->children;
   1565 	}
   1566 #ifdef LIBXML_REGEXP_ENABLED
   1567     } else if ((reader->node != NULL) &&
   1568 	       (reader->node->type == XML_ENTITY_REF_NODE) &&
   1569 	       (reader->ctxt != NULL) && (reader->validate)) {
   1570 	xmlTextReaderValidateEntity(reader);
   1571 #endif /* LIBXML_REGEXP_ENABLED */
   1572     }
   1573     if ((reader->node != NULL) &&
   1574 	(reader->node->type == XML_ENTITY_DECL) &&
   1575 	(reader->ent != NULL) && (reader->ent->children == reader->node)) {
   1576 	reader->node = xmlTextReaderEntPop(reader);
   1577 	reader->depth++;
   1578         goto get_next_node;
   1579     }
   1580 #ifdef LIBXML_REGEXP_ENABLED
   1581     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
   1582 	xmlNodePtr node = reader->node;
   1583 
   1584 	if ((node->type == XML_ELEMENT_NODE) &&
   1585             ((reader->state != XML_TEXTREADER_END) &&
   1586 	     (reader->state != XML_TEXTREADER_BACKTRACK))) {
   1587 	    xmlTextReaderValidatePush(reader);
   1588 	} else if ((node->type == XML_TEXT_NODE) ||
   1589 		   (node->type == XML_CDATA_SECTION_NODE)) {
   1590             xmlTextReaderValidateCData(reader, node->content,
   1591 	                               xmlStrlen(node->content));
   1592 	}
   1593     }
   1594 #endif /* LIBXML_REGEXP_ENABLED */
   1595 #ifdef LIBXML_PATTERN_ENABLED
   1596     if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
   1597         (reader->state != XML_TEXTREADER_BACKTRACK)) {
   1598         int i;
   1599 	for (i = 0;i < reader->patternNr;i++) {
   1600 	     if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
   1601 	         xmlTextReaderPreserve(reader);
   1602 		 break;
   1603              }
   1604 	}
   1605     }
   1606 #endif /* LIBXML_PATTERN_ENABLED */
   1607 #ifdef LIBXML_SCHEMAS_ENABLED
   1608     if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
   1609         (reader->xsdValidErrors == 0) &&
   1610 	(reader->xsdValidCtxt != NULL)) {
   1611 	reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
   1612     }
   1613 #endif /* LIBXML_PATTERN_ENABLED */
   1614     return(1);
   1615 node_end:
   1616     reader->state = XML_TEXTREADER_DONE;
   1617     return(0);
   1618 }
   1619 
   1620 /**
   1621  * xmlTextReaderReadState:
   1622  * @reader:  the xmlTextReaderPtr used
   1623  *
   1624  * Gets the read state of the reader.
   1625  *
   1626  * Returns the state value, or -1 in case of error
   1627  */
   1628 int
   1629 xmlTextReaderReadState(xmlTextReaderPtr reader) {
   1630     if (reader == NULL)
   1631 	return(-1);
   1632     return(reader->mode);
   1633 }
   1634 
   1635 /**
   1636  * xmlTextReaderExpand:
   1637  * @reader:  the xmlTextReaderPtr used
   1638  *
   1639  * Reads the contents of the current node and the full subtree. It then makes
   1640  * the subtree available until the next xmlTextReaderRead() call
   1641  *
   1642  * Returns a node pointer valid until the next xmlTextReaderRead() call
   1643  *         or NULL in case of error.
   1644  */
   1645 xmlNodePtr
   1646 xmlTextReaderExpand(xmlTextReaderPtr reader) {
   1647     if ((reader == NULL) || (reader->node == NULL))
   1648         return(NULL);
   1649     if (reader->doc != NULL)
   1650         return(reader->node);
   1651     if (reader->ctxt == NULL)
   1652         return(NULL);
   1653     if (xmlTextReaderDoExpand(reader) < 0)
   1654         return(NULL);
   1655     return(reader->node);
   1656 }
   1657 
   1658 /**
   1659  * xmlTextReaderNext:
   1660  * @reader:  the xmlTextReaderPtr used
   1661  *
   1662  * Skip to the node following the current one in document order while
   1663  * avoiding the subtree if any.
   1664  *
   1665  * Returns 1 if the node was read successfully, 0 if there is no more
   1666  *          nodes to read, or -1 in case of error
   1667  */
   1668 int
   1669 xmlTextReaderNext(xmlTextReaderPtr reader) {
   1670     int ret;
   1671     xmlNodePtr cur;
   1672 
   1673     if (reader == NULL)
   1674 	return(-1);
   1675     if (reader->doc != NULL)
   1676         return(xmlTextReaderNextTree(reader));
   1677     cur = reader->node;
   1678     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
   1679         return(xmlTextReaderRead(reader));
   1680     if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
   1681         return(xmlTextReaderRead(reader));
   1682     if (cur->extra & NODE_IS_EMPTY)
   1683         return(xmlTextReaderRead(reader));
   1684     do {
   1685         ret = xmlTextReaderRead(reader);
   1686 	if (ret != 1)
   1687 	    return(ret);
   1688     } while (reader->node != cur);
   1689     return(xmlTextReaderRead(reader));
   1690 }
   1691 
   1692 #ifdef LIBXML_WRITER_ENABLED
   1693 /**
   1694  * xmlTextReaderReadInnerXml:
   1695  * @reader:  the xmlTextReaderPtr used
   1696  *
   1697  * Reads the contents of the current node, including child nodes and markup.
   1698  *
   1699  * Returns a string containing the XML content, or NULL if the current node
   1700  *         is neither an element nor attribute, or has no child nodes. The
   1701  *         string must be deallocated by the caller.
   1702  */
   1703 xmlChar *
   1704 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
   1705 {
   1706     xmlChar *resbuf;
   1707     xmlNodePtr node, cur_node;
   1708     xmlBufferPtr buff, buff2;
   1709     xmlDocPtr doc;
   1710 
   1711     if (xmlTextReaderExpand(reader) == NULL) {
   1712         return NULL;
   1713     }
   1714     doc = reader->node->doc;
   1715     buff = xmlBufferCreate();
   1716     for (cur_node = reader->node->children; cur_node != NULL;
   1717          cur_node = cur_node->next) {
   1718         /* XXX: Why is the node copied? */
   1719         node = xmlDocCopyNode(cur_node, doc, 1);
   1720         buff2 = xmlBufferCreate();
   1721         if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
   1722             xmlFreeNode(node);
   1723             xmlBufferFree(buff2);
   1724             xmlBufferFree(buff);
   1725             return NULL;
   1726         }
   1727         xmlBufferCat(buff, buff2->content);
   1728         xmlFreeNode(node);
   1729         xmlBufferFree(buff2);
   1730     }
   1731     resbuf = buff->content;
   1732     buff->content = NULL;
   1733 
   1734     xmlBufferFree(buff);
   1735     return resbuf;
   1736 }
   1737 #endif
   1738 
   1739 #ifdef LIBXML_WRITER_ENABLED
   1740 /**
   1741  * xmlTextReaderReadOuterXml:
   1742  * @reader:  the xmlTextReaderPtr used
   1743  *
   1744  * Reads the contents of the current node, including child nodes and markup.
   1745  *
   1746  * Returns a string containing the node and any XML content, or NULL if the
   1747  *         current node cannot be serialized. The string must be deallocated
   1748  *         by the caller.
   1749  */
   1750 xmlChar *
   1751 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
   1752 {
   1753     xmlChar *resbuf;
   1754     xmlNodePtr node;
   1755     xmlBufferPtr buff;
   1756     xmlDocPtr doc;
   1757 
   1758     node = reader->node;
   1759     doc = node->doc;
   1760     if (xmlTextReaderExpand(reader) == NULL) {
   1761         return NULL;
   1762     }
   1763     /* XXX: Why is the node copied? */
   1764 	if (node->type == XML_DTD_NODE) {
   1765 		node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
   1766 	} else {
   1767 		node = xmlDocCopyNode(node, doc, 1);
   1768 	}
   1769     buff = xmlBufferCreate();
   1770     if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
   1771         xmlFreeNode(node);
   1772         xmlBufferFree(buff);
   1773         return NULL;
   1774     }
   1775 
   1776     resbuf = buff->content;
   1777     buff->content = NULL;
   1778 
   1779     xmlFreeNode(node);
   1780     xmlBufferFree(buff);
   1781     return resbuf;
   1782 }
   1783 #endif
   1784 
   1785 /**
   1786  * xmlTextReaderReadString:
   1787  * @reader:  the xmlTextReaderPtr used
   1788  *
   1789  * Reads the contents of an element or a text node as a string.
   1790  *
   1791  * Returns a string containing the contents of the Element or Text node,
   1792  *         or NULL if the reader is positioned on any other type of node.
   1793  *         The string must be deallocated by the caller.
   1794  */
   1795 xmlChar *
   1796 xmlTextReaderReadString(xmlTextReaderPtr reader)
   1797 {
   1798     xmlNodePtr node;
   1799 
   1800     if ((reader == NULL) || (reader->node == NULL))
   1801        return(NULL);
   1802 
   1803     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
   1804     switch (node->type) {
   1805     case XML_TEXT_NODE:
   1806        if (node->content != NULL)
   1807            return(xmlStrdup(node->content));
   1808        break;
   1809     case XML_ELEMENT_NODE:
   1810 	if (xmlTextReaderDoExpand(reader) != -1) {
   1811 	    return xmlTextReaderCollectSiblings(node->children);
   1812 	}
   1813 	break;
   1814     case XML_ATTRIBUTE_NODE:
   1815 	TODO
   1816 	break;
   1817     default:
   1818        break;
   1819     }
   1820     return(NULL);
   1821 }
   1822 
   1823 #if 0
   1824 /**
   1825  * xmlTextReaderReadBase64:
   1826  * @reader:  the xmlTextReaderPtr used
   1827  * @array:  a byte array to store the content.
   1828  * @offset:  the zero-based index into array where the method should
   1829  *           begin to write.
   1830  * @len:  the number of bytes to write.
   1831  *
   1832  * Reads and decodes the Base64 encoded contents of an element and
   1833  * stores the result in a byte buffer.
   1834  *
   1835  * Returns the number of bytes written to array, or zero if the current
   1836  *         instance is not positioned on an element or -1 in case of error.
   1837  */
   1838 int
   1839 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
   1840                         unsigned char *array ATTRIBUTE_UNUSED,
   1841 	                int offset ATTRIBUTE_UNUSED,
   1842 			int len ATTRIBUTE_UNUSED) {
   1843     if ((reader == NULL) || (reader->ctxt == NULL))
   1844 	return(-1);
   1845     if (reader->ctxt->wellFormed != 1)
   1846 	return(-1);
   1847 
   1848     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
   1849 	return(0);
   1850     TODO
   1851     return(0);
   1852 }
   1853 
   1854 /**
   1855  * xmlTextReaderReadBinHex:
   1856  * @reader:  the xmlTextReaderPtr used
   1857  * @array:  a byte array to store the content.
   1858  * @offset:  the zero-based index into array where the method should
   1859  *           begin to write.
   1860  * @len:  the number of bytes to write.
   1861  *
   1862  * Reads and decodes the BinHex encoded contents of an element and
   1863  * stores the result in a byte buffer.
   1864  *
   1865  * Returns the number of bytes written to array, or zero if the current
   1866  *         instance is not positioned on an element or -1 in case of error.
   1867  */
   1868 int
   1869 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
   1870                         unsigned char *array ATTRIBUTE_UNUSED,
   1871 	                int offset ATTRIBUTE_UNUSED,
   1872 			int len ATTRIBUTE_UNUSED) {
   1873     if ((reader == NULL) || (reader->ctxt == NULL))
   1874 	return(-1);
   1875     if (reader->ctxt->wellFormed != 1)
   1876 	return(-1);
   1877 
   1878     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
   1879 	return(0);
   1880     TODO
   1881     return(0);
   1882 }
   1883 #endif
   1884 
   1885 /************************************************************************
   1886  *									*
   1887  *			Operating on a preparsed tree			*
   1888  *									*
   1889  ************************************************************************/
   1890 static int
   1891 xmlTextReaderNextTree(xmlTextReaderPtr reader)
   1892 {
   1893     if (reader == NULL)
   1894         return(-1);
   1895 
   1896     if (reader->state == XML_TEXTREADER_END)
   1897         return(0);
   1898 
   1899     if (reader->node == NULL) {
   1900         if (reader->doc->children == NULL) {
   1901             reader->state = XML_TEXTREADER_END;
   1902             return(0);
   1903         }
   1904 
   1905         reader->node = reader->doc->children;
   1906         reader->state = XML_TEXTREADER_START;
   1907         return(1);
   1908     }
   1909 
   1910     if (reader->state != XML_TEXTREADER_BACKTRACK) {
   1911 	/* Here removed traversal to child, because we want to skip the subtree,
   1912 	replace with traversal to sibling to skip subtree */
   1913         if (reader->node->next != 0) {
   1914 	    /* Move to sibling if present,skipping sub-tree */
   1915             reader->node = reader->node->next;
   1916             reader->state = XML_TEXTREADER_START;
   1917             return(1);
   1918         }
   1919 
   1920 	/* if reader->node->next is NULL mean no subtree for current node,
   1921 	so need to move to sibling of parent node if present */
   1922 	reader->state = XML_TEXTREADER_BACKTRACK;
   1923 	/* This will move to parent if present */
   1924 	xmlTextReaderRead(reader);
   1925     }
   1926 
   1927     if (reader->node->next != 0) {
   1928         reader->node = reader->node->next;
   1929         reader->state = XML_TEXTREADER_START;
   1930         return(1);
   1931     }
   1932 
   1933     if (reader->node->parent != 0) {
   1934         if (reader->node->parent->type == XML_DOCUMENT_NODE) {
   1935             reader->state = XML_TEXTREADER_END;
   1936             return(0);
   1937         }
   1938 
   1939         reader->node = reader->node->parent;
   1940         reader->depth--;
   1941         reader->state = XML_TEXTREADER_BACKTRACK;
   1942 	/* Repeat process to move to sibling of parent node if present */
   1943         xmlTextReaderNextTree(reader);
   1944     }
   1945 
   1946     reader->state = XML_TEXTREADER_END;
   1947 
   1948     return(1);
   1949 }
   1950 
   1951 /**
   1952  * xmlTextReaderReadTree:
   1953  * @reader:  the xmlTextReaderPtr used
   1954  *
   1955  *  Moves the position of the current instance to the next node in
   1956  *  the stream, exposing its properties.
   1957  *
   1958  *  Returns 1 if the node was read successfully, 0 if there is no more
   1959  *          nodes to read, or -1 in case of error
   1960  */
   1961 static int
   1962 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
   1963     if (reader->state == XML_TEXTREADER_END)
   1964         return(0);
   1965 
   1966 next_node:
   1967     if (reader->node == NULL) {
   1968         if (reader->doc->children == NULL) {
   1969             reader->state = XML_TEXTREADER_END;
   1970             return(0);
   1971         }
   1972 
   1973         reader->node = reader->doc->children;
   1974         reader->state = XML_TEXTREADER_START;
   1975         goto found_node;
   1976     }
   1977 
   1978     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
   1979         (reader->node->type != XML_DTD_NODE) &&
   1980         (reader->node->type != XML_XINCLUDE_START) &&
   1981 	(reader->node->type != XML_ENTITY_REF_NODE)) {
   1982         if (reader->node->children != NULL) {
   1983             reader->node = reader->node->children;
   1984             reader->depth++;
   1985             reader->state = XML_TEXTREADER_START;
   1986             goto found_node;
   1987         }
   1988 
   1989         if (reader->node->type == XML_ATTRIBUTE_NODE) {
   1990             reader->state = XML_TEXTREADER_BACKTRACK;
   1991             goto found_node;
   1992         }
   1993     }
   1994 
   1995     if (reader->node->next != NULL) {
   1996         reader->node = reader->node->next;
   1997         reader->state = XML_TEXTREADER_START;
   1998         goto found_node;
   1999     }
   2000 
   2001     if (reader->node->parent != NULL) {
   2002         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
   2003 	    (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
   2004             reader->state = XML_TEXTREADER_END;
   2005             return(0);
   2006         }
   2007 
   2008         reader->node = reader->node->parent;
   2009         reader->depth--;
   2010         reader->state = XML_TEXTREADER_BACKTRACK;
   2011         goto found_node;
   2012     }
   2013 
   2014     reader->state = XML_TEXTREADER_END;
   2015 
   2016 found_node:
   2017     if ((reader->node->type == XML_XINCLUDE_START) ||
   2018         (reader->node->type == XML_XINCLUDE_END))
   2019 	goto next_node;
   2020 
   2021     return(1);
   2022 }
   2023 
   2024 /**
   2025  * xmlTextReaderNextSibling:
   2026  * @reader:  the xmlTextReaderPtr used
   2027  *
   2028  * Skip to the node following the current one in document order while
   2029  * avoiding the subtree if any.
   2030  * Currently implemented only for Readers built on a document
   2031  *
   2032  * Returns 1 if the node was read successfully, 0 if there is no more
   2033  *          nodes to read, or -1 in case of error
   2034  */
   2035 int
   2036 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
   2037     if (reader == NULL)
   2038         return(-1);
   2039     if (reader->doc == NULL) {
   2040         /* TODO */
   2041 	return(-1);
   2042     }
   2043 
   2044     if (reader->state == XML_TEXTREADER_END)
   2045         return(0);
   2046 
   2047     if (reader->node == NULL)
   2048         return(xmlTextReaderNextTree(reader));
   2049 
   2050     if (reader->node->next != NULL) {
   2051         reader->node = reader->node->next;
   2052         reader->state = XML_TEXTREADER_START;
   2053         return(1);
   2054     }
   2055 
   2056     return(0);
   2057 }
   2058 
   2059 /************************************************************************
   2060  *									*
   2061  *			Constructor and destructors			*
   2062  *									*
   2063  ************************************************************************/
   2064 /**
   2065  * xmlNewTextReader:
   2066  * @input: the xmlParserInputBufferPtr used to read data
   2067  * @URI: the URI information for the source if available
   2068  *
   2069  * Create an xmlTextReader structure fed with @input
   2070  *
   2071  * Returns the new xmlTextReaderPtr or NULL in case of error
   2072  */
   2073 xmlTextReaderPtr
   2074 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
   2075     xmlTextReaderPtr ret;
   2076 
   2077     if (input == NULL)
   2078 	return(NULL);
   2079     ret = xmlMalloc(sizeof(xmlTextReader));
   2080     if (ret == NULL) {
   2081         xmlGenericError(xmlGenericErrorContext,
   2082 		"xmlNewTextReader : malloc failed\n");
   2083 	return(NULL);
   2084     }
   2085     memset(ret, 0, sizeof(xmlTextReader));
   2086     ret->doc = NULL;
   2087     ret->entTab = NULL;
   2088     ret->entMax = 0;
   2089     ret->entNr = 0;
   2090     ret->input = input;
   2091     ret->buffer = xmlBufCreateSize(100);
   2092     if (ret->buffer == NULL) {
   2093         xmlFree(ret);
   2094         xmlGenericError(xmlGenericErrorContext,
   2095 		"xmlNewTextReader : malloc failed\n");
   2096 	return(NULL);
   2097     }
   2098     /* no operation on a reader should require a huge buffer */
   2099     xmlBufSetAllocationScheme(ret->buffer,
   2100 			      XML_BUFFER_ALLOC_BOUNDED);
   2101     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
   2102     if (ret->sax == NULL) {
   2103 	xmlBufFree(ret->buffer);
   2104 	xmlFree(ret);
   2105         xmlGenericError(xmlGenericErrorContext,
   2106 		"xmlNewTextReader : malloc failed\n");
   2107 	return(NULL);
   2108     }
   2109     xmlSAXVersion(ret->sax, 2);
   2110     ret->startElement = ret->sax->startElement;
   2111     ret->sax->startElement = xmlTextReaderStartElement;
   2112     ret->endElement = ret->sax->endElement;
   2113     ret->sax->endElement = xmlTextReaderEndElement;
   2114 #ifdef LIBXML_SAX1_ENABLED
   2115     if (ret->sax->initialized == XML_SAX2_MAGIC) {
   2116 #endif /* LIBXML_SAX1_ENABLED */
   2117 	ret->startElementNs = ret->sax->startElementNs;
   2118 	ret->sax->startElementNs = xmlTextReaderStartElementNs;
   2119 	ret->endElementNs = ret->sax->endElementNs;
   2120 	ret->sax->endElementNs = xmlTextReaderEndElementNs;
   2121 #ifdef LIBXML_SAX1_ENABLED
   2122     } else {
   2123 	ret->startElementNs = NULL;
   2124 	ret->endElementNs = NULL;
   2125     }
   2126 #endif /* LIBXML_SAX1_ENABLED */
   2127     ret->characters = ret->sax->characters;
   2128     ret->sax->characters = xmlTextReaderCharacters;
   2129     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
   2130     ret->cdataBlock = ret->sax->cdataBlock;
   2131     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
   2132 
   2133     ret->mode = XML_TEXTREADER_MODE_INITIAL;
   2134     ret->node = NULL;
   2135     ret->curnode = NULL;
   2136     if (xmlBufUse(ret->input->buffer) < 4) {
   2137 	xmlParserInputBufferRead(input, 4);
   2138     }
   2139     if (xmlBufUse(ret->input->buffer) >= 4) {
   2140 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
   2141 			     (const char *) xmlBufContent(ret->input->buffer),
   2142                                             4, URI);
   2143 	ret->base = 0;
   2144 	ret->cur = 4;
   2145     } else {
   2146 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
   2147 	ret->base = 0;
   2148 	ret->cur = 0;
   2149     }
   2150 
   2151     if (ret->ctxt == NULL) {
   2152         xmlGenericError(xmlGenericErrorContext,
   2153 		"xmlNewTextReader : malloc failed\n");
   2154 	xmlBufFree(ret->buffer);
   2155 	xmlFree(ret->sax);
   2156 	xmlFree(ret);
   2157 	return(NULL);
   2158     }
   2159     ret->ctxt->parseMode = XML_PARSE_READER;
   2160     ret->ctxt->_private = ret;
   2161     ret->ctxt->linenumbers = 1;
   2162     ret->ctxt->dictNames = 1;
   2163     ret->allocs = XML_TEXTREADER_CTXT;
   2164     /*
   2165      * use the parser dictionary to allocate all elements and attributes names
   2166      */
   2167     ret->ctxt->docdict = 1;
   2168     ret->dict = ret->ctxt->dict;
   2169 #ifdef LIBXML_XINCLUDE_ENABLED
   2170     ret->xinclude = 0;
   2171 #endif
   2172 #ifdef LIBXML_PATTERN_ENABLED
   2173     ret->patternMax = 0;
   2174     ret->patternTab = NULL;
   2175 #endif
   2176     return(ret);
   2177 }
   2178 
   2179 /**
   2180  * xmlNewTextReaderFilename:
   2181  * @URI: the URI of the resource to process
   2182  *
   2183  * Create an xmlTextReader structure fed with the resource at @URI
   2184  *
   2185  * Returns the new xmlTextReaderPtr or NULL in case of error
   2186  */
   2187 xmlTextReaderPtr
   2188 xmlNewTextReaderFilename(const char *URI) {
   2189     xmlParserInputBufferPtr input;
   2190     xmlTextReaderPtr ret;
   2191     char *directory = NULL;
   2192 
   2193     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
   2194     if (input == NULL)
   2195 	return(NULL);
   2196     ret = xmlNewTextReader(input, URI);
   2197     if (ret == NULL) {
   2198 	xmlFreeParserInputBuffer(input);
   2199 	return(NULL);
   2200     }
   2201     ret->allocs |= XML_TEXTREADER_INPUT;
   2202     if (ret->ctxt->directory == NULL)
   2203         directory = xmlParserGetDirectory(URI);
   2204     if ((ret->ctxt->directory == NULL) && (directory != NULL))
   2205         ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
   2206     if (directory != NULL)
   2207 	xmlFree(directory);
   2208     return(ret);
   2209 }
   2210 
   2211 /**
   2212  * xmlFreeTextReader:
   2213  * @reader:  the xmlTextReaderPtr
   2214  *
   2215  * Deallocate all the resources associated to the reader
   2216  */
   2217 void
   2218 xmlFreeTextReader(xmlTextReaderPtr reader) {
   2219     if (reader == NULL)
   2220 	return;
   2221 #ifdef LIBXML_SCHEMAS_ENABLED
   2222     if (reader->rngSchemas != NULL) {
   2223 	xmlRelaxNGFree(reader->rngSchemas);
   2224 	reader->rngSchemas = NULL;
   2225     }
   2226     if (reader->rngValidCtxt != NULL) {
   2227 	if (! reader->rngPreserveCtxt)
   2228 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   2229 	reader->rngValidCtxt = NULL;
   2230     }
   2231     if (reader->xsdPlug != NULL) {
   2232 	xmlSchemaSAXUnplug(reader->xsdPlug);
   2233 	reader->xsdPlug = NULL;
   2234     }
   2235     if (reader->xsdValidCtxt != NULL) {
   2236 	if (! reader->xsdPreserveCtxt)
   2237 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   2238 	reader->xsdValidCtxt = NULL;
   2239     }
   2240     if (reader->xsdSchemas != NULL) {
   2241 	xmlSchemaFree(reader->xsdSchemas);
   2242 	reader->xsdSchemas = NULL;
   2243     }
   2244 #endif
   2245 #ifdef LIBXML_XINCLUDE_ENABLED
   2246     if (reader->xincctxt != NULL)
   2247 	xmlXIncludeFreeContext(reader->xincctxt);
   2248 #endif
   2249 #ifdef LIBXML_PATTERN_ENABLED
   2250     if (reader->patternTab != NULL) {
   2251         int i;
   2252 	for (i = 0;i < reader->patternNr;i++) {
   2253 	    if (reader->patternTab[i] != NULL)
   2254 	        xmlFreePattern(reader->patternTab[i]);
   2255 	}
   2256 	xmlFree(reader->patternTab);
   2257     }
   2258 #endif
   2259     if (reader->faketext != NULL) {
   2260 	xmlFreeNode(reader->faketext);
   2261     }
   2262     if (reader->ctxt != NULL) {
   2263         if (reader->dict == reader->ctxt->dict)
   2264 	    reader->dict = NULL;
   2265 	if (reader->ctxt->myDoc != NULL) {
   2266 	    if (reader->preserve == 0)
   2267 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
   2268 	    reader->ctxt->myDoc = NULL;
   2269 	}
   2270 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
   2271 	    (reader->ctxt->vctxt.vstateMax > 0)){
   2272 	    xmlFree(reader->ctxt->vctxt.vstateTab);
   2273 	    reader->ctxt->vctxt.vstateTab = NULL;
   2274 	    reader->ctxt->vctxt.vstateMax = 0;
   2275 	}
   2276 	if (reader->allocs & XML_TEXTREADER_CTXT)
   2277 	    xmlFreeParserCtxt(reader->ctxt);
   2278     }
   2279     if (reader->sax != NULL)
   2280 	xmlFree(reader->sax);
   2281     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
   2282 	xmlFreeParserInputBuffer(reader->input);
   2283     if (reader->buffer != NULL)
   2284         xmlBufFree(reader->buffer);
   2285     if (reader->entTab != NULL)
   2286 	xmlFree(reader->entTab);
   2287     if (reader->dict != NULL)
   2288         xmlDictFree(reader->dict);
   2289     xmlFree(reader);
   2290 }
   2291 
   2292 /************************************************************************
   2293  *									*
   2294  *			Methods for XmlTextReader			*
   2295  *									*
   2296  ************************************************************************/
   2297 /**
   2298  * xmlTextReaderClose:
   2299  * @reader:  the xmlTextReaderPtr used
   2300  *
   2301  * This method releases any resources allocated by the current instance
   2302  * changes the state to Closed and close any underlying input.
   2303  *
   2304  * Returns 0 or -1 in case of error
   2305  */
   2306 int
   2307 xmlTextReaderClose(xmlTextReaderPtr reader) {
   2308     if (reader == NULL)
   2309 	return(-1);
   2310     reader->node = NULL;
   2311     reader->curnode = NULL;
   2312     reader->mode = XML_TEXTREADER_MODE_CLOSED;
   2313     if (reader->ctxt != NULL) {
   2314 	xmlStopParser(reader->ctxt);
   2315 	if (reader->ctxt->myDoc != NULL) {
   2316 	    if (reader->preserve == 0)
   2317 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
   2318 	    reader->ctxt->myDoc = NULL;
   2319 	}
   2320     }
   2321     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
   2322 	xmlFreeParserInputBuffer(reader->input);
   2323 	reader->allocs -= XML_TEXTREADER_INPUT;
   2324     }
   2325     return(0);
   2326 }
   2327 
   2328 /**
   2329  * xmlTextReaderGetAttributeNo:
   2330  * @reader:  the xmlTextReaderPtr used
   2331  * @no: the zero-based index of the attribute relative to the containing element
   2332  *
   2333  * Provides the value of the attribute with the specified index relative
   2334  * to the containing element.
   2335  *
   2336  * Returns a string containing the value of the specified attribute, or NULL
   2337  *    in case of error. The string must be deallocated by the caller.
   2338  */
   2339 xmlChar *
   2340 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
   2341     xmlChar *ret;
   2342     int i;
   2343     xmlAttrPtr cur;
   2344     xmlNsPtr ns;
   2345 
   2346     if (reader == NULL)
   2347 	return(NULL);
   2348     if (reader->node == NULL)
   2349 	return(NULL);
   2350     if (reader->curnode != NULL)
   2351 	return(NULL);
   2352     /* TODO: handle the xmlDecl */
   2353     if (reader->node->type != XML_ELEMENT_NODE)
   2354 	return(NULL);
   2355 
   2356     ns = reader->node->nsDef;
   2357     for (i = 0;(i < no) && (ns != NULL);i++) {
   2358 	ns = ns->next;
   2359     }
   2360     if (ns != NULL)
   2361 	return(xmlStrdup(ns->href));
   2362 
   2363     cur = reader->node->properties;
   2364     if (cur == NULL)
   2365 	return(NULL);
   2366     for (;i < no;i++) {
   2367 	cur = cur->next;
   2368 	if (cur == NULL)
   2369 	    return(NULL);
   2370     }
   2371     /* TODO walk the DTD if present */
   2372 
   2373     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
   2374     if (ret == NULL) return(xmlStrdup((xmlChar *)""));
   2375     return(ret);
   2376 }
   2377 
   2378 /**
   2379  * xmlTextReaderGetAttribute:
   2380  * @reader:  the xmlTextReaderPtr used
   2381  * @name: the qualified name of the attribute.
   2382  *
   2383  * Provides the value of the attribute with the specified qualified name.
   2384  *
   2385  * Returns a string containing the value of the specified attribute, or NULL
   2386  *    in case of error. The string must be deallocated by the caller.
   2387  */
   2388 xmlChar *
   2389 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
   2390     xmlChar *prefix = NULL;
   2391     xmlChar *localname;
   2392     xmlNsPtr ns;
   2393     xmlChar *ret = NULL;
   2394 
   2395     if ((reader == NULL) || (name == NULL))
   2396 	return(NULL);
   2397     if (reader->node == NULL)
   2398 	return(NULL);
   2399     if (reader->curnode != NULL)
   2400 	return(NULL);
   2401 
   2402     /* TODO: handle the xmlDecl */
   2403     if (reader->node->type != XML_ELEMENT_NODE)
   2404 	return(NULL);
   2405 
   2406     localname = xmlSplitQName2(name, &prefix);
   2407     if (localname == NULL) {
   2408 		/*
   2409 		 * Namespace default decl
   2410 		 */
   2411 		if (xmlStrEqual(name, BAD_CAST "xmlns")) {
   2412 			ns = reader->node->nsDef;
   2413 			while (ns != NULL) {
   2414 				if (ns->prefix == NULL) {
   2415 					return(xmlStrdup(ns->href));
   2416 				}
   2417 				ns = ns->next;
   2418 			}
   2419 			return NULL;
   2420 		}
   2421 		return(xmlGetNoNsProp(reader->node, name));
   2422 	}
   2423 
   2424     /*
   2425      * Namespace default decl
   2426      */
   2427     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
   2428 		ns = reader->node->nsDef;
   2429 		while (ns != NULL) {
   2430 			if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
   2431 				ret = xmlStrdup(ns->href);
   2432 				break;
   2433 			}
   2434 			ns = ns->next;
   2435 		}
   2436     } else {
   2437 		ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
   2438 		if (ns != NULL)
   2439 			ret = xmlGetNsProp(reader->node, localname, ns->href);
   2440 	}
   2441 
   2442     xmlFree(localname);
   2443     if (prefix != NULL)
   2444         xmlFree(prefix);
   2445     return(ret);
   2446 }
   2447 
   2448 
   2449 /**
   2450  * xmlTextReaderGetAttributeNs:
   2451  * @reader:  the xmlTextReaderPtr used
   2452  * @localName: the local name of the attribute.
   2453  * @namespaceURI: the namespace URI of the attribute.
   2454  *
   2455  * Provides the value of the specified attribute
   2456  *
   2457  * Returns a string containing the value of the specified attribute, or NULL
   2458  *    in case of error. The string must be deallocated by the caller.
   2459  */
   2460 xmlChar *
   2461 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
   2462 			    const xmlChar *namespaceURI) {
   2463     xmlChar *prefix = NULL;
   2464     xmlNsPtr ns;
   2465 
   2466     if ((reader == NULL) || (localName == NULL))
   2467 	return(NULL);
   2468     if (reader->node == NULL)
   2469 	return(NULL);
   2470     if (reader->curnode != NULL)
   2471 	return(NULL);
   2472 
   2473     /* TODO: handle the xmlDecl */
   2474     if (reader->node->type != XML_ELEMENT_NODE)
   2475 	return(NULL);
   2476 
   2477     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
   2478 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
   2479 			prefix = BAD_CAST localName;
   2480 		}
   2481 		ns = reader->node->nsDef;
   2482 		while (ns != NULL) {
   2483 			if ((prefix == NULL && ns->prefix == NULL) ||
   2484 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
   2485 				return xmlStrdup(ns->href);
   2486 			}
   2487 			ns = ns->next;
   2488 		}
   2489 		return NULL;
   2490     }
   2491 
   2492     return(xmlGetNsProp(reader->node, localName, namespaceURI));
   2493 }
   2494 
   2495 /**
   2496  * xmlTextReaderGetRemainder:
   2497  * @reader:  the xmlTextReaderPtr used
   2498  *
   2499  * Method to get the remainder of the buffered XML. this method stops the
   2500  * parser, set its state to End Of File and return the input stream with
   2501  * what is left that the parser did not use.
   2502  *
   2503  * The implementation is not good, the parser certainly procgressed past
   2504  * what's left in reader->input, and there is an allocation problem. Best
   2505  * would be to rewrite it differently.
   2506  *
   2507  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
   2508  *    in case of error.
   2509  */
   2510 xmlParserInputBufferPtr
   2511 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
   2512     xmlParserInputBufferPtr ret = NULL;
   2513 
   2514     if (reader == NULL)
   2515 	return(NULL);
   2516     if (reader->node == NULL)
   2517 	return(NULL);
   2518 
   2519     reader->node = NULL;
   2520     reader->curnode = NULL;
   2521     reader->mode = XML_TEXTREADER_MODE_EOF;
   2522     if (reader->ctxt != NULL) {
   2523 	xmlStopParser(reader->ctxt);
   2524 	if (reader->ctxt->myDoc != NULL) {
   2525 	    if (reader->preserve == 0)
   2526 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
   2527 	    reader->ctxt->myDoc = NULL;
   2528 	}
   2529     }
   2530     if (reader->allocs & XML_TEXTREADER_INPUT) {
   2531 	ret = reader->input;
   2532 	reader->input = NULL;
   2533 	reader->allocs -= XML_TEXTREADER_INPUT;
   2534     } else {
   2535 	/*
   2536 	 * Hum, one may need to duplicate the data structure because
   2537 	 * without reference counting the input may be freed twice:
   2538 	 *   - by the layer which allocated it.
   2539 	 *   - by the layer to which would have been returned to.
   2540 	 */
   2541 	TODO
   2542 	return(NULL);
   2543     }
   2544     return(ret);
   2545 }
   2546 
   2547 /**
   2548  * xmlTextReaderLookupNamespace:
   2549  * @reader:  the xmlTextReaderPtr used
   2550  * @prefix: the prefix whose namespace URI is to be resolved. To return
   2551  *          the default namespace, specify NULL
   2552  *
   2553  * Resolves a namespace prefix in the scope of the current element.
   2554  *
   2555  * Returns a string containing the namespace URI to which the prefix maps
   2556  *    or NULL in case of error. The string must be deallocated by the caller.
   2557  */
   2558 xmlChar *
   2559 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
   2560     xmlNsPtr ns;
   2561 
   2562     if (reader == NULL)
   2563 	return(NULL);
   2564     if (reader->node == NULL)
   2565 	return(NULL);
   2566 
   2567     ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
   2568     if (ns == NULL)
   2569 	return(NULL);
   2570     return(xmlStrdup(ns->href));
   2571 }
   2572 
   2573 /**
   2574  * xmlTextReaderMoveToAttributeNo:
   2575  * @reader:  the xmlTextReaderPtr used
   2576  * @no: the zero-based index of the attribute relative to the containing
   2577  *      element.
   2578  *
   2579  * Moves the position of the current instance to the attribute with
   2580  * the specified index relative to the containing element.
   2581  *
   2582  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2583  */
   2584 int
   2585 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
   2586     int i;
   2587     xmlAttrPtr cur;
   2588     xmlNsPtr ns;
   2589 
   2590     if (reader == NULL)
   2591 	return(-1);
   2592     if (reader->node == NULL)
   2593 	return(-1);
   2594     /* TODO: handle the xmlDecl */
   2595     if (reader->node->type != XML_ELEMENT_NODE)
   2596 	return(-1);
   2597 
   2598     reader->curnode = NULL;
   2599 
   2600     ns = reader->node->nsDef;
   2601     for (i = 0;(i < no) && (ns != NULL);i++) {
   2602 	ns = ns->next;
   2603     }
   2604     if (ns != NULL) {
   2605 	reader->curnode = (xmlNodePtr) ns;
   2606 	return(1);
   2607     }
   2608 
   2609     cur = reader->node->properties;
   2610     if (cur == NULL)
   2611 	return(0);
   2612     for (;i < no;i++) {
   2613 	cur = cur->next;
   2614 	if (cur == NULL)
   2615 	    return(0);
   2616     }
   2617     /* TODO walk the DTD if present */
   2618 
   2619     reader->curnode = (xmlNodePtr) cur;
   2620     return(1);
   2621 }
   2622 
   2623 /**
   2624  * xmlTextReaderMoveToAttribute:
   2625  * @reader:  the xmlTextReaderPtr used
   2626  * @name: the qualified name of the attribute.
   2627  *
   2628  * Moves the position of the current instance to the attribute with
   2629  * the specified qualified name.
   2630  *
   2631  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2632  */
   2633 int
   2634 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
   2635     xmlChar *prefix = NULL;
   2636     xmlChar *localname;
   2637     xmlNsPtr ns;
   2638     xmlAttrPtr prop;
   2639 
   2640     if ((reader == NULL) || (name == NULL))
   2641 	return(-1);
   2642     if (reader->node == NULL)
   2643 	return(-1);
   2644 
   2645     /* TODO: handle the xmlDecl */
   2646     if (reader->node->type != XML_ELEMENT_NODE)
   2647 	return(0);
   2648 
   2649     localname = xmlSplitQName2(name, &prefix);
   2650     if (localname == NULL) {
   2651 	/*
   2652 	 * Namespace default decl
   2653 	 */
   2654 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
   2655 	    ns = reader->node->nsDef;
   2656 	    while (ns != NULL) {
   2657 		if (ns->prefix == NULL) {
   2658 		    reader->curnode = (xmlNodePtr) ns;
   2659 		    return(1);
   2660 		}
   2661 		ns = ns->next;
   2662 	    }
   2663 	    return(0);
   2664 	}
   2665 
   2666 	prop = reader->node->properties;
   2667 	while (prop != NULL) {
   2668 	    /*
   2669 	     * One need to have
   2670 	     *   - same attribute names
   2671 	     *   - and the attribute carrying that namespace
   2672 	     */
   2673 	    if ((xmlStrEqual(prop->name, name)) &&
   2674 		((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
   2675 		reader->curnode = (xmlNodePtr) prop;
   2676 		return(1);
   2677 	    }
   2678 	    prop = prop->next;
   2679 	}
   2680 	return(0);
   2681     }
   2682 
   2683     /*
   2684      * Namespace default decl
   2685      */
   2686     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
   2687 	ns = reader->node->nsDef;
   2688 	while (ns != NULL) {
   2689 	    if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
   2690 		reader->curnode = (xmlNodePtr) ns;
   2691 		goto found;
   2692 	    }
   2693 	    ns = ns->next;
   2694 	}
   2695 	goto not_found;
   2696     }
   2697     prop = reader->node->properties;
   2698     while (prop != NULL) {
   2699 	/*
   2700 	 * One need to have
   2701 	 *   - same attribute names
   2702 	 *   - and the attribute carrying that namespace
   2703 	 */
   2704 	if ((xmlStrEqual(prop->name, localname)) &&
   2705 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
   2706 	    reader->curnode = (xmlNodePtr) prop;
   2707 	    goto found;
   2708 	}
   2709 	prop = prop->next;
   2710     }
   2711 not_found:
   2712     if (localname != NULL)
   2713         xmlFree(localname);
   2714     if (prefix != NULL)
   2715         xmlFree(prefix);
   2716     return(0);
   2717 
   2718 found:
   2719     if (localname != NULL)
   2720         xmlFree(localname);
   2721     if (prefix != NULL)
   2722         xmlFree(prefix);
   2723     return(1);
   2724 }
   2725 
   2726 /**
   2727  * xmlTextReaderMoveToAttributeNs:
   2728  * @reader:  the xmlTextReaderPtr used
   2729  * @localName:  the local name of the attribute.
   2730  * @namespaceURI:  the namespace URI of the attribute.
   2731  *
   2732  * Moves the position of the current instance to the attribute with the
   2733  * specified local name and namespace URI.
   2734  *
   2735  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2736  */
   2737 int
   2738 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
   2739 	const xmlChar *localName, const xmlChar *namespaceURI) {
   2740     xmlAttrPtr prop;
   2741     xmlNodePtr node;
   2742     xmlNsPtr ns;
   2743     xmlChar *prefix = NULL;
   2744 
   2745     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
   2746 	return(-1);
   2747     if (reader->node == NULL)
   2748 	return(-1);
   2749     if (reader->node->type != XML_ELEMENT_NODE)
   2750 	return(0);
   2751     node = reader->node;
   2752 
   2753     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
   2754 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
   2755 			prefix = BAD_CAST localName;
   2756 		}
   2757 		ns = reader->node->nsDef;
   2758 		while (ns != NULL) {
   2759 			if ((prefix == NULL && ns->prefix == NULL) ||
   2760 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
   2761 				reader->curnode = (xmlNodePtr) ns;
   2762 				return(1);
   2763 			}
   2764 			ns = ns->next;
   2765 		}
   2766 		return(0);
   2767     }
   2768 
   2769     prop = node->properties;
   2770     while (prop != NULL) {
   2771 	/*
   2772 	 * One need to have
   2773 	 *   - same attribute names
   2774 	 *   - and the attribute carrying that namespace
   2775 	 */
   2776         if (xmlStrEqual(prop->name, localName) &&
   2777 	    ((prop->ns != NULL) &&
   2778 	     (xmlStrEqual(prop->ns->href, namespaceURI)))) {
   2779 	    reader->curnode = (xmlNodePtr) prop;
   2780 	    return(1);
   2781         }
   2782 	prop = prop->next;
   2783     }
   2784     return(0);
   2785 }
   2786 
   2787 /**
   2788  * xmlTextReaderMoveToFirstAttribute:
   2789  * @reader:  the xmlTextReaderPtr used
   2790  *
   2791  * Moves the position of the current instance to the first attribute
   2792  * associated with the current node.
   2793  *
   2794  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2795  */
   2796 int
   2797 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
   2798     if (reader == NULL)
   2799 	return(-1);
   2800     if (reader->node == NULL)
   2801 	return(-1);
   2802     if (reader->node->type != XML_ELEMENT_NODE)
   2803 	return(0);
   2804 
   2805     if (reader->node->nsDef != NULL) {
   2806 	reader->curnode = (xmlNodePtr) reader->node->nsDef;
   2807 	return(1);
   2808     }
   2809     if (reader->node->properties != NULL) {
   2810 	reader->curnode = (xmlNodePtr) reader->node->properties;
   2811 	return(1);
   2812     }
   2813     return(0);
   2814 }
   2815 
   2816 /**
   2817  * xmlTextReaderMoveToNextAttribute:
   2818  * @reader:  the xmlTextReaderPtr used
   2819  *
   2820  * Moves the position of the current instance to the next attribute
   2821  * associated with the current node.
   2822  *
   2823  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2824  */
   2825 int
   2826 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
   2827     if (reader == NULL)
   2828 	return(-1);
   2829     if (reader->node == NULL)
   2830 	return(-1);
   2831     if (reader->node->type != XML_ELEMENT_NODE)
   2832 	return(0);
   2833     if (reader->curnode == NULL)
   2834 	return(xmlTextReaderMoveToFirstAttribute(reader));
   2835 
   2836     if (reader->curnode->type == XML_NAMESPACE_DECL) {
   2837 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
   2838 	if (ns->next != NULL) {
   2839 	    reader->curnode = (xmlNodePtr) ns->next;
   2840 	    return(1);
   2841 	}
   2842 	if (reader->node->properties != NULL) {
   2843 	    reader->curnode = (xmlNodePtr) reader->node->properties;
   2844 	    return(1);
   2845 	}
   2846 	return(0);
   2847     } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
   2848 	       (reader->curnode->next != NULL)) {
   2849 	reader->curnode = reader->curnode->next;
   2850 	return(1);
   2851     }
   2852     return(0);
   2853 }
   2854 
   2855 /**
   2856  * xmlTextReaderMoveToElement:
   2857  * @reader:  the xmlTextReaderPtr used
   2858  *
   2859  * Moves the position of the current instance to the node that
   2860  * contains the current Attribute  node.
   2861  *
   2862  * Returns 1 in case of success, -1 in case of error, 0 if not moved
   2863  */
   2864 int
   2865 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
   2866     if (reader == NULL)
   2867 	return(-1);
   2868     if (reader->node == NULL)
   2869 	return(-1);
   2870     if (reader->node->type != XML_ELEMENT_NODE)
   2871 	return(0);
   2872     if (reader->curnode != NULL) {
   2873 	reader->curnode = NULL;
   2874 	return(1);
   2875     }
   2876     return(0);
   2877 }
   2878 
   2879 /**
   2880  * xmlTextReaderReadAttributeValue:
   2881  * @reader:  the xmlTextReaderPtr used
   2882  *
   2883  * Parses an attribute value into one or more Text and EntityReference nodes.
   2884  *
   2885  * Returns 1 in case of success, 0 if the reader was not positionned on an
   2886  *         ttribute node or all the attribute values have been read, or -1
   2887  *         in case of error.
   2888  */
   2889 int
   2890 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
   2891     if (reader == NULL)
   2892 	return(-1);
   2893     if (reader->node == NULL)
   2894 	return(-1);
   2895     if (reader->curnode == NULL)
   2896 	return(0);
   2897     if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
   2898 	if (reader->curnode->children == NULL)
   2899 	    return(0);
   2900 	reader->curnode = reader->curnode->children;
   2901     } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
   2902 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
   2903 
   2904 	if (reader->faketext == NULL) {
   2905 	    reader->faketext = xmlNewDocText(reader->node->doc,
   2906 		                             ns->href);
   2907 	} else {
   2908             if ((reader->faketext->content != NULL) &&
   2909 	        (reader->faketext->content !=
   2910 		 (xmlChar *) &(reader->faketext->properties)))
   2911 		xmlFree(reader->faketext->content);
   2912 	    reader->faketext->content = xmlStrdup(ns->href);
   2913 	}
   2914 	reader->curnode = reader->faketext;
   2915     } else {
   2916 	if (reader->curnode->next == NULL)
   2917 	    return(0);
   2918 	reader->curnode = reader->curnode->next;
   2919     }
   2920     return(1);
   2921 }
   2922 
   2923 /**
   2924  * xmlTextReaderConstEncoding:
   2925  * @reader:  the xmlTextReaderPtr used
   2926  *
   2927  * Determine the encoding of the document being read.
   2928  *
   2929  * Returns a string containing the encoding of the document or NULL in
   2930  * case of error.  The string is deallocated with the reader.
   2931  */
   2932 const xmlChar *
   2933 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
   2934     xmlDocPtr doc = NULL;
   2935     if (reader == NULL)
   2936 	return(NULL);
   2937     if (reader->doc != NULL)
   2938         doc = reader->doc;
   2939     else if (reader->ctxt != NULL)
   2940 	doc = reader->ctxt->myDoc;
   2941     if (doc == NULL)
   2942 	return(NULL);
   2943 
   2944     if (doc->encoding == NULL)
   2945 	return(NULL);
   2946     else
   2947       return(CONSTSTR(doc->encoding));
   2948 }
   2949 
   2950 
   2951 /************************************************************************
   2952  *									*
   2953  *			Acces API to the current node			*
   2954  *									*
   2955  ************************************************************************/
   2956 /**
   2957  * xmlTextReaderAttributeCount:
   2958  * @reader:  the xmlTextReaderPtr used
   2959  *
   2960  * Provides the number of attributes of the current node
   2961  *
   2962  * Returns 0 i no attributes, -1 in case of error or the attribute count
   2963  */
   2964 int
   2965 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
   2966     int ret;
   2967     xmlAttrPtr attr;
   2968     xmlNsPtr ns;
   2969     xmlNodePtr node;
   2970 
   2971     if (reader == NULL)
   2972 	return(-1);
   2973     if (reader->node == NULL)
   2974 	return(0);
   2975 
   2976     if (reader->curnode != NULL)
   2977 	node = reader->curnode;
   2978     else
   2979 	node = reader->node;
   2980 
   2981     if (node->type != XML_ELEMENT_NODE)
   2982 	return(0);
   2983     if ((reader->state == XML_TEXTREADER_END) ||
   2984 	(reader->state == XML_TEXTREADER_BACKTRACK))
   2985 	return(0);
   2986     ret = 0;
   2987     attr = node->properties;
   2988     while (attr != NULL) {
   2989 	ret++;
   2990 	attr = attr->next;
   2991     }
   2992     ns = node->nsDef;
   2993     while (ns != NULL) {
   2994 	ret++;
   2995 	ns = ns->next;
   2996     }
   2997     return(ret);
   2998 }
   2999 
   3000 /**
   3001  * xmlTextReaderNodeType:
   3002  * @reader:  the xmlTextReaderPtr used
   3003  *
   3004  * Get the node type of the current node
   3005  * Reference:
   3006  * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
   3007  *
   3008  * Returns the xmlReaderTypes of the current node or -1 in case of error
   3009  */
   3010 int
   3011 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
   3012     xmlNodePtr node;
   3013 
   3014     if (reader == NULL)
   3015 	return(-1);
   3016     if (reader->node == NULL)
   3017 	return(XML_READER_TYPE_NONE);
   3018     if (reader->curnode != NULL)
   3019 	node = reader->curnode;
   3020     else
   3021 	node = reader->node;
   3022     switch (node->type) {
   3023         case XML_ELEMENT_NODE:
   3024 	    if ((reader->state == XML_TEXTREADER_END) ||
   3025 		(reader->state == XML_TEXTREADER_BACKTRACK))
   3026 		return(XML_READER_TYPE_END_ELEMENT);
   3027 	    return(XML_READER_TYPE_ELEMENT);
   3028         case XML_NAMESPACE_DECL:
   3029         case XML_ATTRIBUTE_NODE:
   3030 	    return(XML_READER_TYPE_ATTRIBUTE);
   3031         case XML_TEXT_NODE:
   3032 	    if (xmlIsBlankNode(reader->node)) {
   3033 		if (xmlNodeGetSpacePreserve(reader->node))
   3034 		    return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
   3035 		else
   3036 		    return(XML_READER_TYPE_WHITESPACE);
   3037 	    } else {
   3038 		return(XML_READER_TYPE_TEXT);
   3039 	    }
   3040         case XML_CDATA_SECTION_NODE:
   3041 	    return(XML_READER_TYPE_CDATA);
   3042         case XML_ENTITY_REF_NODE:
   3043 	    return(XML_READER_TYPE_ENTITY_REFERENCE);
   3044         case XML_ENTITY_NODE:
   3045 	    return(XML_READER_TYPE_ENTITY);
   3046         case XML_PI_NODE:
   3047 	    return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
   3048         case XML_COMMENT_NODE:
   3049 	    return(XML_READER_TYPE_COMMENT);
   3050         case XML_DOCUMENT_NODE:
   3051         case XML_HTML_DOCUMENT_NODE:
   3052 #ifdef LIBXML_DOCB_ENABLED
   3053         case XML_DOCB_DOCUMENT_NODE:
   3054 #endif
   3055 	    return(XML_READER_TYPE_DOCUMENT);
   3056         case XML_DOCUMENT_FRAG_NODE:
   3057 	    return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
   3058         case XML_NOTATION_NODE:
   3059 	    return(XML_READER_TYPE_NOTATION);
   3060         case XML_DOCUMENT_TYPE_NODE:
   3061         case XML_DTD_NODE:
   3062 	    return(XML_READER_TYPE_DOCUMENT_TYPE);
   3063 
   3064         case XML_ELEMENT_DECL:
   3065         case XML_ATTRIBUTE_DECL:
   3066         case XML_ENTITY_DECL:
   3067         case XML_XINCLUDE_START:
   3068         case XML_XINCLUDE_END:
   3069 	    return(XML_READER_TYPE_NONE);
   3070     }
   3071     return(-1);
   3072 }
   3073 
   3074 /**
   3075  * xmlTextReaderIsEmptyElement:
   3076  * @reader:  the xmlTextReaderPtr used
   3077  *
   3078  * Check if the current node is empty
   3079  *
   3080  * Returns 1 if empty, 0 if not and -1 in case of error
   3081  */
   3082 int
   3083 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
   3084     if ((reader == NULL) || (reader->node == NULL))
   3085 	return(-1);
   3086     if (reader->node->type != XML_ELEMENT_NODE)
   3087 	return(0);
   3088     if (reader->curnode != NULL)
   3089 	return(0);
   3090     if (reader->node->children != NULL)
   3091 	return(0);
   3092     if (reader->state == XML_TEXTREADER_END)
   3093 	return(0);
   3094     if (reader->doc != NULL)
   3095         return(1);
   3096 #ifdef LIBXML_XINCLUDE_ENABLED
   3097     if (reader->in_xinclude > 0)
   3098         return(1);
   3099 #endif
   3100     return((reader->node->extra & NODE_IS_EMPTY) != 0);
   3101 }
   3102 
   3103 /**
   3104  * xmlTextReaderLocalName:
   3105  * @reader:  the xmlTextReaderPtr used
   3106  *
   3107  * The local name of the node.
   3108  *
   3109  * Returns the local name or NULL if not available,
   3110  *   if non NULL it need to be freed by the caller.
   3111  */
   3112 xmlChar *
   3113 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
   3114     xmlNodePtr node;
   3115     if ((reader == NULL) || (reader->node == NULL))
   3116 	return(NULL);
   3117     if (reader->curnode != NULL)
   3118 	node = reader->curnode;
   3119     else
   3120 	node = reader->node;
   3121     if (node->type == XML_NAMESPACE_DECL) {
   3122 	xmlNsPtr ns = (xmlNsPtr) node;
   3123 	if (ns->prefix == NULL)
   3124 	    return(xmlStrdup(BAD_CAST "xmlns"));
   3125 	else
   3126 	    return(xmlStrdup(ns->prefix));
   3127     }
   3128     if ((node->type != XML_ELEMENT_NODE) &&
   3129 	(node->type != XML_ATTRIBUTE_NODE))
   3130 	return(xmlTextReaderName(reader));
   3131     return(xmlStrdup(node->name));
   3132 }
   3133 
   3134 /**
   3135  * xmlTextReaderConstLocalName:
   3136  * @reader:  the xmlTextReaderPtr used
   3137  *
   3138  * The local name of the node.
   3139  *
   3140  * Returns the local name or NULL if not available, the
   3141  *         string will be deallocated with the reader.
   3142  */
   3143 const xmlChar *
   3144 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
   3145     xmlNodePtr node;
   3146     if ((reader == NULL) || (reader->node == NULL))
   3147 	return(NULL);
   3148     if (reader->curnode != NULL)
   3149 	node = reader->curnode;
   3150     else
   3151 	node = reader->node;
   3152     if (node->type == XML_NAMESPACE_DECL) {
   3153 	xmlNsPtr ns = (xmlNsPtr) node;
   3154 	if (ns->prefix == NULL)
   3155 	    return(CONSTSTR(BAD_CAST "xmlns"));
   3156 	else
   3157 	    return(ns->prefix);
   3158     }
   3159     if ((node->type != XML_ELEMENT_NODE) &&
   3160 	(node->type != XML_ATTRIBUTE_NODE))
   3161 	return(xmlTextReaderConstName(reader));
   3162     return(node->name);
   3163 }
   3164 
   3165 /**
   3166  * xmlTextReaderName:
   3167  * @reader:  the xmlTextReaderPtr used
   3168  *
   3169  * The qualified name of the node, equal to Prefix :LocalName.
   3170  *
   3171  * Returns the local name or NULL if not available,
   3172  *   if non NULL it need to be freed by the caller.
   3173  */
   3174 xmlChar *
   3175 xmlTextReaderName(xmlTextReaderPtr reader) {
   3176     xmlNodePtr node;
   3177     xmlChar *ret;
   3178 
   3179     if ((reader == NULL) || (reader->node == NULL))
   3180 	return(NULL);
   3181     if (reader->curnode != NULL)
   3182 	node = reader->curnode;
   3183     else
   3184 	node = reader->node;
   3185     switch (node->type) {
   3186         case XML_ELEMENT_NODE:
   3187         case XML_ATTRIBUTE_NODE:
   3188 	    if ((node->ns == NULL) ||
   3189 		(node->ns->prefix == NULL))
   3190 		return(xmlStrdup(node->name));
   3191 
   3192 	    ret = xmlStrdup(node->ns->prefix);
   3193 	    ret = xmlStrcat(ret, BAD_CAST ":");
   3194 	    ret = xmlStrcat(ret, node->name);
   3195 	    return(ret);
   3196         case XML_TEXT_NODE:
   3197 	    return(xmlStrdup(BAD_CAST "#text"));
   3198         case XML_CDATA_SECTION_NODE:
   3199 	    return(xmlStrdup(BAD_CAST "#cdata-section"));
   3200         case XML_ENTITY_NODE:
   3201         case XML_ENTITY_REF_NODE:
   3202 	    return(xmlStrdup(node->name));
   3203         case XML_PI_NODE:
   3204 	    return(xmlStrdup(node->name));
   3205         case XML_COMMENT_NODE:
   3206 	    return(xmlStrdup(BAD_CAST "#comment"));
   3207         case XML_DOCUMENT_NODE:
   3208         case XML_HTML_DOCUMENT_NODE:
   3209 #ifdef LIBXML_DOCB_ENABLED
   3210         case XML_DOCB_DOCUMENT_NODE:
   3211 #endif
   3212 	    return(xmlStrdup(BAD_CAST "#document"));
   3213         case XML_DOCUMENT_FRAG_NODE:
   3214 	    return(xmlStrdup(BAD_CAST "#document-fragment"));
   3215         case XML_NOTATION_NODE:
   3216 	    return(xmlStrdup(node->name));
   3217         case XML_DOCUMENT_TYPE_NODE:
   3218         case XML_DTD_NODE:
   3219 	    return(xmlStrdup(node->name));
   3220         case XML_NAMESPACE_DECL: {
   3221 	    xmlNsPtr ns = (xmlNsPtr) node;
   3222 
   3223 	    ret = xmlStrdup(BAD_CAST "xmlns");
   3224 	    if (ns->prefix == NULL)
   3225 		return(ret);
   3226 	    ret = xmlStrcat(ret, BAD_CAST ":");
   3227 	    ret = xmlStrcat(ret, ns->prefix);
   3228 	    return(ret);
   3229 	}
   3230 
   3231         case XML_ELEMENT_DECL:
   3232         case XML_ATTRIBUTE_DECL:
   3233         case XML_ENTITY_DECL:
   3234         case XML_XINCLUDE_START:
   3235         case XML_XINCLUDE_END:
   3236 	    return(NULL);
   3237     }
   3238     return(NULL);
   3239 }
   3240 
   3241 /**
   3242  * xmlTextReaderConstName:
   3243  * @reader:  the xmlTextReaderPtr used
   3244  *
   3245  * The qualified name of the node, equal to Prefix :LocalName.
   3246  *
   3247  * Returns the local name or NULL if not available, the string is
   3248  *         deallocated with the reader.
   3249  */
   3250 const xmlChar *
   3251 xmlTextReaderConstName(xmlTextReaderPtr reader) {
   3252     xmlNodePtr node;
   3253 
   3254     if ((reader == NULL) || (reader->node == NULL))
   3255 	return(NULL);
   3256     if (reader->curnode != NULL)
   3257 	node = reader->curnode;
   3258     else
   3259 	node = reader->node;
   3260     switch (node->type) {
   3261         case XML_ELEMENT_NODE:
   3262         case XML_ATTRIBUTE_NODE:
   3263 	    if ((node->ns == NULL) ||
   3264 		(node->ns->prefix == NULL))
   3265 		return(node->name);
   3266 	    return(CONSTQSTR(node->ns->prefix, node->name));
   3267         case XML_TEXT_NODE:
   3268 	    return(CONSTSTR(BAD_CAST "#text"));
   3269         case XML_CDATA_SECTION_NODE:
   3270 	    return(CONSTSTR(BAD_CAST "#cdata-section"));
   3271         case XML_ENTITY_NODE:
   3272         case XML_ENTITY_REF_NODE:
   3273 	    return(CONSTSTR(node->name));
   3274         case XML_PI_NODE:
   3275 	    return(CONSTSTR(node->name));
   3276         case XML_COMMENT_NODE:
   3277 	    return(CONSTSTR(BAD_CAST "#comment"));
   3278         case XML_DOCUMENT_NODE:
   3279         case XML_HTML_DOCUMENT_NODE:
   3280 #ifdef LIBXML_DOCB_ENABLED
   3281         case XML_DOCB_DOCUMENT_NODE:
   3282 #endif
   3283 	    return(CONSTSTR(BAD_CAST "#document"));
   3284         case XML_DOCUMENT_FRAG_NODE:
   3285 	    return(CONSTSTR(BAD_CAST "#document-fragment"));
   3286         case XML_NOTATION_NODE:
   3287 	    return(CONSTSTR(node->name));
   3288         case XML_DOCUMENT_TYPE_NODE:
   3289         case XML_DTD_NODE:
   3290 	    return(CONSTSTR(node->name));
   3291         case XML_NAMESPACE_DECL: {
   3292 	    xmlNsPtr ns = (xmlNsPtr) node;
   3293 
   3294 	    if (ns->prefix == NULL)
   3295 		return(CONSTSTR(BAD_CAST "xmlns"));
   3296 	    return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
   3297 	}
   3298 
   3299         case XML_ELEMENT_DECL:
   3300         case XML_ATTRIBUTE_DECL:
   3301         case XML_ENTITY_DECL:
   3302         case XML_XINCLUDE_START:
   3303         case XML_XINCLUDE_END:
   3304 	    return(NULL);
   3305     }
   3306     return(NULL);
   3307 }
   3308 
   3309 /**
   3310  * xmlTextReaderPrefix:
   3311  * @reader:  the xmlTextReaderPtr used
   3312  *
   3313  * A shorthand reference to the namespace associated with the node.
   3314  *
   3315  * Returns the prefix or NULL if not available,
   3316  *    if non NULL it need to be freed by the caller.
   3317  */
   3318 xmlChar *
   3319 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
   3320     xmlNodePtr node;
   3321     if ((reader == NULL) || (reader->node == NULL))
   3322 	return(NULL);
   3323     if (reader->curnode != NULL)
   3324 	node = reader->curnode;
   3325     else
   3326 	node = reader->node;
   3327     if (node->type == XML_NAMESPACE_DECL) {
   3328 	xmlNsPtr ns = (xmlNsPtr) node;
   3329 	if (ns->prefix == NULL)
   3330 	    return(NULL);
   3331 	return(xmlStrdup(BAD_CAST "xmlns"));
   3332     }
   3333     if ((node->type != XML_ELEMENT_NODE) &&
   3334 	(node->type != XML_ATTRIBUTE_NODE))
   3335 	return(NULL);
   3336     if ((node->ns != NULL) && (node->ns->prefix != NULL))
   3337 	return(xmlStrdup(node->ns->prefix));
   3338     return(NULL);
   3339 }
   3340 
   3341 /**
   3342  * xmlTextReaderConstPrefix:
   3343  * @reader:  the xmlTextReaderPtr used
   3344  *
   3345  * A shorthand reference to the namespace associated with the node.
   3346  *
   3347  * Returns the prefix or NULL if not available, the string is deallocated
   3348  *         with the reader.
   3349  */
   3350 const xmlChar *
   3351 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
   3352     xmlNodePtr node;
   3353     if ((reader == NULL) || (reader->node == NULL))
   3354 	return(NULL);
   3355     if (reader->curnode != NULL)
   3356 	node = reader->curnode;
   3357     else
   3358 	node = reader->node;
   3359     if (node->type == XML_NAMESPACE_DECL) {
   3360 	xmlNsPtr ns = (xmlNsPtr) node;
   3361 	if (ns->prefix == NULL)
   3362 	    return(NULL);
   3363 	return(CONSTSTR(BAD_CAST "xmlns"));
   3364     }
   3365     if ((node->type != XML_ELEMENT_NODE) &&
   3366 	(node->type != XML_ATTRIBUTE_NODE))
   3367 	return(NULL);
   3368     if ((node->ns != NULL) && (node->ns->prefix != NULL))
   3369 	return(CONSTSTR(node->ns->prefix));
   3370     return(NULL);
   3371 }
   3372 
   3373 /**
   3374  * xmlTextReaderNamespaceUri:
   3375  * @reader:  the xmlTextReaderPtr used
   3376  *
   3377  * The URI defining the namespace associated with the node.
   3378  *
   3379  * Returns the namespace URI or NULL if not available,
   3380  *    if non NULL it need to be freed by the caller.
   3381  */
   3382 xmlChar *
   3383 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
   3384     xmlNodePtr node;
   3385     if ((reader == NULL) || (reader->node == NULL))
   3386 	return(NULL);
   3387     if (reader->curnode != NULL)
   3388 	node = reader->curnode;
   3389     else
   3390 	node = reader->node;
   3391     if (node->type == XML_NAMESPACE_DECL)
   3392 	return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
   3393     if ((node->type != XML_ELEMENT_NODE) &&
   3394 	(node->type != XML_ATTRIBUTE_NODE))
   3395 	return(NULL);
   3396     if (node->ns != NULL)
   3397 	return(xmlStrdup(node->ns->href));
   3398     return(NULL);
   3399 }
   3400 
   3401 /**
   3402  * xmlTextReaderConstNamespaceUri:
   3403  * @reader:  the xmlTextReaderPtr used
   3404  *
   3405  * The URI defining the namespace associated with the node.
   3406  *
   3407  * Returns the namespace URI or NULL if not available, the string
   3408  *         will be deallocated with the reader
   3409  */
   3410 const xmlChar *
   3411 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
   3412     xmlNodePtr node;
   3413     if ((reader == NULL) || (reader->node == NULL))
   3414 	return(NULL);
   3415     if (reader->curnode != NULL)
   3416 	node = reader->curnode;
   3417     else
   3418 	node = reader->node;
   3419     if (node->type == XML_NAMESPACE_DECL)
   3420 	return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
   3421     if ((node->type != XML_ELEMENT_NODE) &&
   3422 	(node->type != XML_ATTRIBUTE_NODE))
   3423 	return(NULL);
   3424     if (node->ns != NULL)
   3425 	return(CONSTSTR(node->ns->href));
   3426     return(NULL);
   3427 }
   3428 
   3429 /**
   3430  * xmlTextReaderBaseUri:
   3431  * @reader:  the xmlTextReaderPtr used
   3432  *
   3433  * The base URI of the node.
   3434  *
   3435  * Returns the base URI or NULL if not available,
   3436  *    if non NULL it need to be freed by the caller.
   3437  */
   3438 xmlChar *
   3439 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
   3440     if ((reader == NULL) || (reader->node == NULL))
   3441 	return(NULL);
   3442     return(xmlNodeGetBase(NULL, reader->node));
   3443 }
   3444 
   3445 /**
   3446  * xmlTextReaderConstBaseUri:
   3447  * @reader:  the xmlTextReaderPtr used
   3448  *
   3449  * The base URI of the node.
   3450  *
   3451  * Returns the base URI or NULL if not available, the string
   3452  *         will be deallocated with the reader
   3453  */
   3454 const xmlChar *
   3455 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
   3456     xmlChar *tmp;
   3457     const xmlChar *ret;
   3458 
   3459     if ((reader == NULL) || (reader->node == NULL))
   3460 	return(NULL);
   3461     tmp = xmlNodeGetBase(NULL, reader->node);
   3462     if (tmp == NULL)
   3463         return(NULL);
   3464     ret = CONSTSTR(tmp);
   3465     xmlFree(tmp);
   3466     return(ret);
   3467 }
   3468 
   3469 /**
   3470  * xmlTextReaderDepth:
   3471  * @reader:  the xmlTextReaderPtr used
   3472  *
   3473  * The depth of the node in the tree.
   3474  *
   3475  * Returns the depth or -1 in case of error
   3476  */
   3477 int
   3478 xmlTextReaderDepth(xmlTextReaderPtr reader) {
   3479     if (reader == NULL)
   3480 	return(-1);
   3481     if (reader->node == NULL)
   3482 	return(0);
   3483 
   3484     if (reader->curnode != NULL) {
   3485 	if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
   3486 	    (reader->curnode->type == XML_NAMESPACE_DECL))
   3487 	    return(reader->depth + 1);
   3488 	return(reader->depth + 2);
   3489     }
   3490     return(reader->depth);
   3491 }
   3492 
   3493 /**
   3494  * xmlTextReaderHasAttributes:
   3495  * @reader:  the xmlTextReaderPtr used
   3496  *
   3497  * Whether the node has attributes.
   3498  *
   3499  * Returns 1 if true, 0 if false, and -1 in case or error
   3500  */
   3501 int
   3502 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
   3503     xmlNodePtr node;
   3504     if (reader == NULL)
   3505 	return(-1);
   3506     if (reader->node == NULL)
   3507 	return(0);
   3508     if (reader->curnode != NULL)
   3509 	node = reader->curnode;
   3510     else
   3511 	node = reader->node;
   3512 
   3513     if ((node->type == XML_ELEMENT_NODE) &&
   3514 	((node->properties != NULL) || (node->nsDef != NULL)))
   3515 	return(1);
   3516     /* TODO: handle the xmlDecl */
   3517     return(0);
   3518 }
   3519 
   3520 /**
   3521  * xmlTextReaderHasValue:
   3522  * @reader:  the xmlTextReaderPtr used
   3523  *
   3524  * Whether the node can have a text value.
   3525  *
   3526  * Returns 1 if true, 0 if false, and -1 in case or error
   3527  */
   3528 int
   3529 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
   3530     xmlNodePtr node;
   3531     if (reader == NULL)
   3532 	return(-1);
   3533     if (reader->node == NULL)
   3534 	return(0);
   3535     if (reader->curnode != NULL)
   3536 	node = reader->curnode;
   3537     else
   3538 	node = reader->node;
   3539 
   3540     switch (node->type) {
   3541         case XML_ATTRIBUTE_NODE:
   3542         case XML_TEXT_NODE:
   3543         case XML_CDATA_SECTION_NODE:
   3544         case XML_PI_NODE:
   3545         case XML_COMMENT_NODE:
   3546         case XML_NAMESPACE_DECL:
   3547 	    return(1);
   3548 	default:
   3549 	    break;
   3550     }
   3551     return(0);
   3552 }
   3553 
   3554 /**
   3555  * xmlTextReaderValue:
   3556  * @reader:  the xmlTextReaderPtr used
   3557  *
   3558  * Provides the text value of the node if present
   3559  *
   3560  * Returns the string or NULL if not available. The result must be deallocated
   3561  *     with xmlFree()
   3562  */
   3563 xmlChar *
   3564 xmlTextReaderValue(xmlTextReaderPtr reader) {
   3565     xmlNodePtr node;
   3566     if (reader == NULL)
   3567 	return(NULL);
   3568     if (reader->node == NULL)
   3569 	return(NULL);
   3570     if (reader->curnode != NULL)
   3571 	node = reader->curnode;
   3572     else
   3573 	node = reader->node;
   3574 
   3575     switch (node->type) {
   3576         case XML_NAMESPACE_DECL:
   3577 	    return(xmlStrdup(((xmlNsPtr) node)->href));
   3578         case XML_ATTRIBUTE_NODE:{
   3579 	    xmlAttrPtr attr = (xmlAttrPtr) node;
   3580 
   3581 	    if (attr->parent != NULL)
   3582 		return (xmlNodeListGetString
   3583 			(attr->parent->doc, attr->children, 1));
   3584 	    else
   3585 		return (xmlNodeListGetString(NULL, attr->children, 1));
   3586 	    break;
   3587 	}
   3588         case XML_TEXT_NODE:
   3589         case XML_CDATA_SECTION_NODE:
   3590         case XML_PI_NODE:
   3591         case XML_COMMENT_NODE:
   3592             if (node->content != NULL)
   3593                 return (xmlStrdup(node->content));
   3594 	default:
   3595 	    break;
   3596     }
   3597     return(NULL);
   3598 }
   3599 
   3600 /**
   3601  * xmlTextReaderConstValue:
   3602  * @reader:  the xmlTextReaderPtr used
   3603  *
   3604  * Provides the text value of the node if present
   3605  *
   3606  * Returns the string or NULL if not available. The result will be
   3607  *     deallocated on the next Read() operation.
   3608  */
   3609 const xmlChar *
   3610 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
   3611     xmlNodePtr node;
   3612     if (reader == NULL)
   3613 	return(NULL);
   3614     if (reader->node == NULL)
   3615 	return(NULL);
   3616     if (reader->curnode != NULL)
   3617 	node = reader->curnode;
   3618     else
   3619 	node = reader->node;
   3620 
   3621     switch (node->type) {
   3622         case XML_NAMESPACE_DECL:
   3623 	    return(((xmlNsPtr) node)->href);
   3624         case XML_ATTRIBUTE_NODE:{
   3625 	    xmlAttrPtr attr = (xmlAttrPtr) node;
   3626 	    const xmlChar *ret;
   3627 
   3628 	    if ((attr->children != NULL) &&
   3629 	        (attr->children->type == XML_TEXT_NODE) &&
   3630 		(attr->children->next == NULL))
   3631 		return(attr->children->content);
   3632 	    else {
   3633 		if (reader->buffer == NULL) {
   3634 		    reader->buffer = xmlBufCreateSize(100);
   3635                     if (reader->buffer == NULL) {
   3636                         xmlGenericError(xmlGenericErrorContext,
   3637                                         "xmlTextReaderSetup : malloc failed\n");
   3638                         return (NULL);
   3639                     }
   3640 		    xmlBufSetAllocationScheme(reader->buffer,
   3641 		                              XML_BUFFER_ALLOC_BOUNDED);
   3642                 } else
   3643                     xmlBufEmpty(reader->buffer);
   3644 	        xmlBufGetNodeContent(reader->buffer, node);
   3645 		ret = xmlBufContent(reader->buffer);
   3646 		if (ret == NULL) {
   3647 		    /* error on the buffer best to reallocate */
   3648 		    xmlBufFree(reader->buffer);
   3649 		    reader->buffer = xmlBufCreateSize(100);
   3650 		    xmlBufSetAllocationScheme(reader->buffer,
   3651 		                              XML_BUFFER_ALLOC_BOUNDED);
   3652 		    ret = BAD_CAST "";
   3653 		}
   3654 		return(ret);
   3655 	    }
   3656 	    break;
   3657 	}
   3658         case XML_TEXT_NODE:
   3659         case XML_CDATA_SECTION_NODE:
   3660         case XML_PI_NODE:
   3661         case XML_COMMENT_NODE:
   3662 	    return(node->content);
   3663 	default:
   3664 	    break;
   3665     }
   3666     return(NULL);
   3667 }
   3668 
   3669 /**
   3670  * xmlTextReaderIsDefault:
   3671  * @reader:  the xmlTextReaderPtr used
   3672  *
   3673  * Whether an Attribute  node was generated from the default value
   3674  * defined in the DTD or schema.
   3675  *
   3676  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
   3677  */
   3678 int
   3679 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
   3680     if (reader == NULL)
   3681 	return(-1);
   3682     return(0);
   3683 }
   3684 
   3685 /**
   3686  * xmlTextReaderQuoteChar:
   3687  * @reader:  the xmlTextReaderPtr used
   3688  *
   3689  * The quotation mark character used to enclose the value of an attribute.
   3690  *
   3691  * Returns " or ' and -1 in case of error
   3692  */
   3693 int
   3694 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
   3695     if (reader == NULL)
   3696 	return(-1);
   3697     /* TODO maybe lookup the attribute value for " first */
   3698     return((int) '"');
   3699 }
   3700 
   3701 /**
   3702  * xmlTextReaderXmlLang:
   3703  * @reader:  the xmlTextReaderPtr used
   3704  *
   3705  * The xml:lang scope within which the node resides.
   3706  *
   3707  * Returns the xml:lang value or NULL if none exists.,
   3708  *    if non NULL it need to be freed by the caller.
   3709  */
   3710 xmlChar *
   3711 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
   3712     if (reader == NULL)
   3713 	return(NULL);
   3714     if (reader->node == NULL)
   3715 	return(NULL);
   3716     return(xmlNodeGetLang(reader->node));
   3717 }
   3718 
   3719 /**
   3720  * xmlTextReaderConstXmlLang:
   3721  * @reader:  the xmlTextReaderPtr used
   3722  *
   3723  * The xml:lang scope within which the node resides.
   3724  *
   3725  * Returns the xml:lang value or NULL if none exists.
   3726  */
   3727 const xmlChar *
   3728 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
   3729     xmlChar *tmp;
   3730     const xmlChar *ret;
   3731 
   3732     if (reader == NULL)
   3733 	return(NULL);
   3734     if (reader->node == NULL)
   3735 	return(NULL);
   3736     tmp = xmlNodeGetLang(reader->node);
   3737     if (tmp == NULL)
   3738         return(NULL);
   3739     ret = CONSTSTR(tmp);
   3740     xmlFree(tmp);
   3741     return(ret);
   3742 }
   3743 
   3744 /**
   3745  * xmlTextReaderConstString:
   3746  * @reader:  the xmlTextReaderPtr used
   3747  * @str:  the string to intern.
   3748  *
   3749  * Get an interned string from the reader, allows for example to
   3750  * speedup string name comparisons
   3751  *
   3752  * Returns an interned copy of the string or NULL in case of error. The
   3753  *         string will be deallocated with the reader.
   3754  */
   3755 const xmlChar *
   3756 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
   3757     if (reader == NULL)
   3758 	return(NULL);
   3759     return(CONSTSTR(str));
   3760 }
   3761 
   3762 /**
   3763  * xmlTextReaderNormalization:
   3764  * @reader:  the xmlTextReaderPtr used
   3765  *
   3766  * The value indicating whether to normalize white space and attribute values.
   3767  * Since attribute value and end of line normalizations are a MUST in the XML
   3768  * specification only the value true is accepted. The broken bahaviour of
   3769  * accepting out of range character entities like &#0; is of course not
   3770  * supported either.
   3771  *
   3772  * Returns 1 or -1 in case of error.
   3773  */
   3774 int
   3775 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
   3776     if (reader == NULL)
   3777 	return(-1);
   3778     return(1);
   3779 }
   3780 
   3781 /************************************************************************
   3782  *									*
   3783  *			Extensions to the base APIs			*
   3784  *									*
   3785  ************************************************************************/
   3786 
   3787 /**
   3788  * xmlTextReaderSetParserProp:
   3789  * @reader:  the xmlTextReaderPtr used
   3790  * @prop:  the xmlParserProperties to set
   3791  * @value:  usually 0 or 1 to (de)activate it
   3792  *
   3793  * Change the parser processing behaviour by changing some of its internal
   3794  * properties. Note that some properties can only be changed before any
   3795  * read has been done.
   3796  *
   3797  * Returns 0 if the call was successful, or -1 in case of error
   3798  */
   3799 int
   3800 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
   3801     xmlParserProperties p = (xmlParserProperties) prop;
   3802     xmlParserCtxtPtr ctxt;
   3803 
   3804     if ((reader == NULL) || (reader->ctxt == NULL))
   3805 	return(-1);
   3806     ctxt = reader->ctxt;
   3807 
   3808     switch (p) {
   3809         case XML_PARSER_LOADDTD:
   3810 	    if (value != 0) {
   3811 		if (ctxt->loadsubset == 0) {
   3812 		    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   3813 			return(-1);
   3814 		    ctxt->loadsubset = XML_DETECT_IDS;
   3815 		}
   3816 	    } else {
   3817 		ctxt->loadsubset = 0;
   3818 	    }
   3819 	    return(0);
   3820         case XML_PARSER_DEFAULTATTRS:
   3821 	    if (value != 0) {
   3822 		ctxt->loadsubset |= XML_COMPLETE_ATTRS;
   3823 	    } else {
   3824 		if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
   3825 		    ctxt->loadsubset -= XML_COMPLETE_ATTRS;
   3826 	    }
   3827 	    return(0);
   3828         case XML_PARSER_VALIDATE:
   3829 	    if (value != 0) {
   3830 		ctxt->validate = 1;
   3831 		reader->validate = XML_TEXTREADER_VALIDATE_DTD;
   3832 	    } else {
   3833 		ctxt->validate = 0;
   3834 	    }
   3835 	    return(0);
   3836         case XML_PARSER_SUBST_ENTITIES:
   3837 	    if (value != 0) {
   3838 		ctxt->replaceEntities = 1;
   3839 	    } else {
   3840 		ctxt->replaceEntities = 0;
   3841 	    }
   3842 	    return(0);
   3843     }
   3844     return(-1);
   3845 }
   3846 
   3847 /**
   3848  * xmlTextReaderGetParserProp:
   3849  * @reader:  the xmlTextReaderPtr used
   3850  * @prop:  the xmlParserProperties to get
   3851  *
   3852  * Read the parser internal property.
   3853  *
   3854  * Returns the value, usually 0 or 1, or -1 in case of error.
   3855  */
   3856 int
   3857 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
   3858     xmlParserProperties p = (xmlParserProperties) prop;
   3859     xmlParserCtxtPtr ctxt;
   3860 
   3861     if ((reader == NULL) || (reader->ctxt == NULL))
   3862 	return(-1);
   3863     ctxt = reader->ctxt;
   3864 
   3865     switch (p) {
   3866         case XML_PARSER_LOADDTD:
   3867 	    if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
   3868 		return(1);
   3869 	    return(0);
   3870         case XML_PARSER_DEFAULTATTRS:
   3871 	    if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
   3872 		return(1);
   3873 	    return(0);
   3874         case XML_PARSER_VALIDATE:
   3875 	    return(reader->validate);
   3876 	case XML_PARSER_SUBST_ENTITIES:
   3877 	    return(ctxt->replaceEntities);
   3878     }
   3879     return(-1);
   3880 }
   3881 
   3882 
   3883 /**
   3884  * xmlTextReaderGetParserLineNumber:
   3885  * @reader: the user data (XML reader context)
   3886  *
   3887  * Provide the line number of the current parsing point.
   3888  *
   3889  * Returns an int or 0 if not available
   3890  */
   3891 int
   3892 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
   3893 {
   3894     if ((reader == NULL) || (reader->ctxt == NULL) ||
   3895         (reader->ctxt->input == NULL)) {
   3896         return (0);
   3897     }
   3898     return (reader->ctxt->input->line);
   3899 }
   3900 
   3901 /**
   3902  * xmlTextReaderGetParserColumnNumber:
   3903  * @reader: the user data (XML reader context)
   3904  *
   3905  * Provide the column number of the current parsing point.
   3906  *
   3907  * Returns an int or 0 if not available
   3908  */
   3909 int
   3910 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
   3911 {
   3912     if ((reader == NULL) || (reader->ctxt == NULL) ||
   3913         (reader->ctxt->input == NULL)) {
   3914         return (0);
   3915     }
   3916     return (reader->ctxt->input->col);
   3917 }
   3918 
   3919 /**
   3920  * xmlTextReaderCurrentNode:
   3921  * @reader:  the xmlTextReaderPtr used
   3922  *
   3923  * Hacking interface allowing to get the xmlNodePtr correponding to the
   3924  * current node being accessed by the xmlTextReader. This is dangerous
   3925  * because the underlying node may be destroyed on the next Reads.
   3926  *
   3927  * Returns the xmlNodePtr or NULL in case of error.
   3928  */
   3929 xmlNodePtr
   3930 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
   3931     if (reader == NULL)
   3932 	return(NULL);
   3933 
   3934     if (reader->curnode != NULL)
   3935 	return(reader->curnode);
   3936     return(reader->node);
   3937 }
   3938 
   3939 /**
   3940  * xmlTextReaderPreserve:
   3941  * @reader:  the xmlTextReaderPtr used
   3942  *
   3943  * This tells the XML Reader to preserve the current node.
   3944  * The caller must also use xmlTextReaderCurrentDoc() to
   3945  * keep an handle on the resulting document once parsing has finished
   3946  *
   3947  * Returns the xmlNodePtr or NULL in case of error.
   3948  */
   3949 xmlNodePtr
   3950 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
   3951     xmlNodePtr cur, parent;
   3952 
   3953     if (reader == NULL)
   3954 	return(NULL);
   3955 
   3956     if (reader->curnode != NULL)
   3957         cur = reader->curnode;
   3958     else
   3959         cur = reader->node;
   3960     if (cur == NULL)
   3961         return(NULL);
   3962 
   3963     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
   3964 	cur->extra |= NODE_IS_PRESERVED;
   3965 	cur->extra |= NODE_IS_SPRESERVED;
   3966     }
   3967     reader->preserves++;
   3968 
   3969     parent = cur->parent;;
   3970     while (parent != NULL) {
   3971         if (parent->type == XML_ELEMENT_NODE)
   3972 	    parent->extra |= NODE_IS_PRESERVED;
   3973 	parent = parent->parent;
   3974     }
   3975     return(cur);
   3976 }
   3977 
   3978 #ifdef LIBXML_PATTERN_ENABLED
   3979 /**
   3980  * xmlTextReaderPreservePattern:
   3981  * @reader:  the xmlTextReaderPtr used
   3982  * @pattern:  an XPath subset pattern
   3983  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
   3984  *
   3985  * This tells the XML Reader to preserve all nodes matched by the
   3986  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
   3987  * keep an handle on the resulting document once parsing has finished
   3988  *
   3989  * Returns a non-negative number in case of success and -1 in case of error
   3990  */
   3991 int
   3992 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
   3993                              const xmlChar **namespaces)
   3994 {
   3995     xmlPatternPtr comp;
   3996 
   3997     if ((reader == NULL) || (pattern == NULL))
   3998 	return(-1);
   3999 
   4000     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
   4001     if (comp == NULL)
   4002         return(-1);
   4003 
   4004     if (reader->patternMax <= 0) {
   4005 	reader->patternMax = 4;
   4006 	reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
   4007 					      sizeof(reader->patternTab[0]));
   4008         if (reader->patternTab == NULL) {
   4009             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
   4010             return (-1);
   4011         }
   4012     }
   4013     if (reader->patternNr >= reader->patternMax) {
   4014         xmlPatternPtr *tmp;
   4015         reader->patternMax *= 2;
   4016 	tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
   4017                                       reader->patternMax *
   4018                                       sizeof(reader->patternTab[0]));
   4019         if (tmp == NULL) {
   4020             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
   4021 	    reader->patternMax /= 2;
   4022             return (-1);
   4023         }
   4024 	reader->patternTab = tmp;
   4025     }
   4026     reader->patternTab[reader->patternNr] = comp;
   4027     return(reader->patternNr++);
   4028 }
   4029 #endif
   4030 
   4031 /**
   4032  * xmlTextReaderCurrentDoc:
   4033  * @reader:  the xmlTextReaderPtr used
   4034  *
   4035  * Hacking interface allowing to get the xmlDocPtr correponding to the
   4036  * current document being accessed by the xmlTextReader.
   4037  * NOTE: as a result of this call, the reader will not destroy the
   4038  *       associated XML document and calling xmlFreeDoc() on the result
   4039  *       is needed once the reader parsing has finished.
   4040  *
   4041  * Returns the xmlDocPtr or NULL in case of error.
   4042  */
   4043 xmlDocPtr
   4044 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
   4045     if (reader == NULL)
   4046 	return(NULL);
   4047     if (reader->doc != NULL)
   4048         return(reader->doc);
   4049     if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
   4050 	return(NULL);
   4051 
   4052     reader->preserve = 1;
   4053     return(reader->ctxt->myDoc);
   4054 }
   4055 
   4056 #ifdef LIBXML_SCHEMAS_ENABLED
   4057 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
   4058 
   4059 static void XMLCDECL
   4060 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
   4061 
   4062 static void XMLCDECL
   4063 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
   4064 
   4065 static void XMLCDECL
   4066 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
   4067 
   4068 static void XMLCDECL
   4069 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
   4070 
   4071 static void XMLCDECL
   4072 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
   4073 {
   4074     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
   4075 
   4076     char *str;
   4077 
   4078     va_list ap;
   4079 
   4080     va_start(ap, msg);
   4081     str = xmlTextReaderBuildMessage(msg, ap);
   4082     if (!reader->errorFunc) {
   4083         xmlTextReaderValidityError(ctx, "%s", str);
   4084     } else {
   4085         reader->errorFunc(reader->errorFuncArg, str,
   4086                           XML_PARSER_SEVERITY_VALIDITY_ERROR,
   4087                           NULL /* locator */ );
   4088     }
   4089     if (str != NULL)
   4090         xmlFree(str);
   4091     va_end(ap);
   4092 }
   4093 
   4094 static void XMLCDECL
   4095 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
   4096 {
   4097     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
   4098 
   4099     char *str;
   4100 
   4101     va_list ap;
   4102 
   4103     va_start(ap, msg);
   4104     str = xmlTextReaderBuildMessage(msg, ap);
   4105     if (!reader->errorFunc) {
   4106         xmlTextReaderValidityWarning(ctx, "%s", str);
   4107     } else {
   4108         reader->errorFunc(reader->errorFuncArg, str,
   4109                           XML_PARSER_SEVERITY_VALIDITY_WARNING,
   4110                           NULL /* locator */ );
   4111     }
   4112     if (str != NULL)
   4113         xmlFree(str);
   4114     va_end(ap);
   4115 }
   4116 
   4117 static void
   4118   xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
   4119 
   4120 static void
   4121 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
   4122 {
   4123     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
   4124 
   4125     if (reader->sErrorFunc) {
   4126         reader->sErrorFunc(reader->errorFuncArg, error);
   4127     } else {
   4128         xmlTextReaderStructuredError(reader, error);
   4129     }
   4130 }
   4131 /**
   4132  * xmlTextReaderRelaxNGSetSchema:
   4133  * @reader:  the xmlTextReaderPtr used
   4134  * @schema:  a precompiled RelaxNG schema
   4135  *
   4136  * Use RelaxNG to validate the document as it is processed.
   4137  * Activation is only possible before the first Read().
   4138  * if @schema is NULL, then RelaxNG validation is desactivated.
   4139  @ The @schema should not be freed until the reader is deallocated
   4140  * or its use has been deactivated.
   4141  *
   4142  * Returns 0 in case the RelaxNG validation could be (des)activated and
   4143  *         -1 in case of error.
   4144  */
   4145 int
   4146 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
   4147     if (reader == NULL)
   4148         return(-1);
   4149     if (schema == NULL) {
   4150         if (reader->rngSchemas != NULL) {
   4151 	    xmlRelaxNGFree(reader->rngSchemas);
   4152 	    reader->rngSchemas = NULL;
   4153 	}
   4154         if (reader->rngValidCtxt != NULL) {
   4155 	    if (! reader->rngPreserveCtxt)
   4156 		xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4157 	    reader->rngValidCtxt = NULL;
   4158         }
   4159 	reader->rngPreserveCtxt = 0;
   4160 	return(0);
   4161     }
   4162     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   4163 	return(-1);
   4164     if (reader->rngSchemas != NULL) {
   4165 	xmlRelaxNGFree(reader->rngSchemas);
   4166 	reader->rngSchemas = NULL;
   4167     }
   4168     if (reader->rngValidCtxt != NULL) {
   4169 	if (! reader->rngPreserveCtxt)
   4170 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4171 	reader->rngValidCtxt = NULL;
   4172     }
   4173     reader->rngPreserveCtxt = 0;
   4174     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
   4175     if (reader->rngValidCtxt == NULL)
   4176         return(-1);
   4177     if (reader->errorFunc != NULL) {
   4178 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
   4179 			xmlTextReaderValidityErrorRelay,
   4180 			xmlTextReaderValidityWarningRelay,
   4181 			reader);
   4182     }
   4183 	if (reader->sErrorFunc != NULL) {
   4184 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4185 			xmlTextReaderValidityStructuredRelay,
   4186 			reader);
   4187     }
   4188     reader->rngValidErrors = 0;
   4189     reader->rngFullNode = NULL;
   4190     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
   4191     return(0);
   4192 }
   4193 
   4194 /**
   4195  * xmlTextReaderLocator:
   4196  * @ctx: the xmlTextReaderPtr used
   4197  * @file: returned file information
   4198  * @line: returned line information
   4199  *
   4200  * Internal locator function for the readers
   4201  *
   4202  * Returns 0 in case the Schema validation could be (des)activated and
   4203  *         -1 in case of error.
   4204  */
   4205 static int
   4206 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
   4207     xmlTextReaderPtr reader;
   4208 
   4209     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
   4210         return(-1);
   4211 
   4212     if (file != NULL)
   4213         *file = NULL;
   4214     if (line != NULL)
   4215         *line = 0;
   4216 
   4217     reader = (xmlTextReaderPtr) ctx;
   4218     if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
   4219 	if (file != NULL)
   4220 	    *file = reader->ctxt->input->filename;
   4221 	if (line != NULL)
   4222 	    *line = reader->ctxt->input->line;
   4223 	return(0);
   4224     }
   4225     if (reader->node != NULL) {
   4226         long res;
   4227 	int ret = 0;
   4228 
   4229 	if (line != NULL) {
   4230 	    res = xmlGetLineNo(reader->node);
   4231 	    if (res > 0)
   4232 	        *line = (unsigned long) res;
   4233 	    else
   4234                 ret = -1;
   4235 	}
   4236         if (file != NULL) {
   4237 	    xmlDocPtr doc = reader->node->doc;
   4238 	    if ((doc != NULL) && (doc->URL != NULL))
   4239 	        *file = (const char *) doc->URL;
   4240 	    else
   4241                 ret = -1;
   4242 	}
   4243 	return(ret);
   4244     }
   4245     return(-1);
   4246 }
   4247 
   4248 /**
   4249  * xmlTextReaderSetSchema:
   4250  * @reader:  the xmlTextReaderPtr used
   4251  * @schema:  a precompiled Schema schema
   4252  *
   4253  * Use XSD Schema to validate the document as it is processed.
   4254  * Activation is only possible before the first Read().
   4255  * if @schema is NULL, then Schema validation is desactivated.
   4256  @ The @schema should not be freed until the reader is deallocated
   4257  * or its use has been deactivated.
   4258  *
   4259  * Returns 0 in case the Schema validation could be (des)activated and
   4260  *         -1 in case of error.
   4261  */
   4262 int
   4263 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
   4264     if (reader == NULL)
   4265         return(-1);
   4266     if (schema == NULL) {
   4267 	if (reader->xsdPlug != NULL) {
   4268 	    xmlSchemaSAXUnplug(reader->xsdPlug);
   4269 	    reader->xsdPlug = NULL;
   4270 	}
   4271         if (reader->xsdValidCtxt != NULL) {
   4272 	    if (! reader->xsdPreserveCtxt)
   4273 		xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4274 	    reader->xsdValidCtxt = NULL;
   4275         }
   4276 	reader->xsdPreserveCtxt = 0;
   4277         if (reader->xsdSchemas != NULL) {
   4278 	    xmlSchemaFree(reader->xsdSchemas);
   4279 	    reader->xsdSchemas = NULL;
   4280 	}
   4281 	return(0);
   4282     }
   4283     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   4284 	return(-1);
   4285     if (reader->xsdPlug != NULL) {
   4286 	xmlSchemaSAXUnplug(reader->xsdPlug);
   4287 	reader->xsdPlug = NULL;
   4288     }
   4289     if (reader->xsdValidCtxt != NULL) {
   4290 	if (! reader->xsdPreserveCtxt)
   4291 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4292 	reader->xsdValidCtxt = NULL;
   4293     }
   4294     reader->xsdPreserveCtxt = 0;
   4295     if (reader->xsdSchemas != NULL) {
   4296 	xmlSchemaFree(reader->xsdSchemas);
   4297 	reader->xsdSchemas = NULL;
   4298     }
   4299     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
   4300     if (reader->xsdValidCtxt == NULL) {
   4301 	xmlSchemaFree(reader->xsdSchemas);
   4302 	reader->xsdSchemas = NULL;
   4303         return(-1);
   4304     }
   4305     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
   4306                                        &(reader->ctxt->sax),
   4307 				       &(reader->ctxt->userData));
   4308     if (reader->xsdPlug == NULL) {
   4309 	xmlSchemaFree(reader->xsdSchemas);
   4310 	reader->xsdSchemas = NULL;
   4311 	xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4312 	reader->xsdValidCtxt = NULL;
   4313 	return(-1);
   4314     }
   4315     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
   4316                                 xmlTextReaderLocator,
   4317 				(void *) reader);
   4318 
   4319     if (reader->errorFunc != NULL) {
   4320 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
   4321 			xmlTextReaderValidityErrorRelay,
   4322 			xmlTextReaderValidityWarningRelay,
   4323 			reader);
   4324     }
   4325 	if (reader->sErrorFunc != NULL) {
   4326 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
   4327 			xmlTextReaderValidityStructuredRelay,
   4328 			reader);
   4329     }
   4330     reader->xsdValidErrors = 0;
   4331     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
   4332     return(0);
   4333 }
   4334 
   4335 /**
   4336  * xmlTextReaderRelaxNGValidateInternal:
   4337  * @reader:  the xmlTextReaderPtr used
   4338  * @rng:  the path to a RelaxNG schema or NULL
   4339  * @ctxt: the RelaxNG schema validation context or NULL
   4340  * @options: options (not yet used)
   4341  *
   4342  * Use RelaxNG to validate the document as it is processed.
   4343  * Activation is only possible before the first Read().
   4344  * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
   4345  *
   4346  * Returns 0 in case the RelaxNG validation could be (de)activated and
   4347  *	   -1 in case of error.
   4348  */
   4349 static int
   4350 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
   4351 				     const char *rng,
   4352 				     xmlRelaxNGValidCtxtPtr ctxt,
   4353 				     int options ATTRIBUTE_UNUSED)
   4354 {
   4355     if (reader == NULL)
   4356 	return(-1);
   4357 
   4358     if ((rng != NULL) && (ctxt != NULL))
   4359 	return (-1);
   4360 
   4361     if (((rng != NULL) || (ctxt != NULL)) &&
   4362 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
   4363 	 (reader->ctxt == NULL)))
   4364 	return(-1);
   4365 
   4366     /* Cleanup previous validation stuff. */
   4367     if (reader->rngValidCtxt != NULL) {
   4368 	if ( !reader->rngPreserveCtxt)
   4369 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4370 	reader->rngValidCtxt = NULL;
   4371     }
   4372     reader->rngPreserveCtxt = 0;
   4373     if (reader->rngSchemas != NULL) {
   4374 	xmlRelaxNGFree(reader->rngSchemas);
   4375 	reader->rngSchemas = NULL;
   4376     }
   4377 
   4378     if ((rng == NULL) && (ctxt == NULL)) {
   4379 	/* We just want to deactivate the validation, so get out. */
   4380 	return(0);
   4381     }
   4382 
   4383 
   4384     if (rng != NULL) {
   4385 	xmlRelaxNGParserCtxtPtr pctxt;
   4386 	/* Parse the schema and create validation environment. */
   4387 
   4388 	pctxt = xmlRelaxNGNewParserCtxt(rng);
   4389 	if (reader->errorFunc != NULL) {
   4390 	    xmlRelaxNGSetParserErrors(pctxt,
   4391 		xmlTextReaderValidityErrorRelay,
   4392 		xmlTextReaderValidityWarningRelay,
   4393 		reader);
   4394 	}
   4395 	if (reader->sErrorFunc != NULL) {
   4396 	    xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4397 		xmlTextReaderValidityStructuredRelay,
   4398 		reader);
   4399 	}
   4400 	reader->rngSchemas = xmlRelaxNGParse(pctxt);
   4401 	xmlRelaxNGFreeParserCtxt(pctxt);
   4402 	if (reader->rngSchemas == NULL)
   4403 	    return(-1);
   4404 	reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
   4405 	if (reader->rngValidCtxt == NULL) {
   4406 	    xmlRelaxNGFree(reader->rngSchemas);
   4407 	    reader->rngSchemas = NULL;
   4408 	    return(-1);
   4409 	}
   4410     } else {
   4411 	/* Use the given validation context. */
   4412 	reader->rngValidCtxt = ctxt;
   4413 	reader->rngPreserveCtxt = 1;
   4414     }
   4415     /*
   4416     * Redirect the validation context's error channels to use
   4417     * the reader channels.
   4418     * TODO: In case the user provides the validation context we
   4419     *	could make this redirection optional.
   4420     */
   4421     if (reader->errorFunc != NULL) {
   4422 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
   4423 			 xmlTextReaderValidityErrorRelay,
   4424 			 xmlTextReaderValidityWarningRelay,
   4425 			 reader);
   4426     }
   4427 	if (reader->sErrorFunc != NULL) {
   4428 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4429 			xmlTextReaderValidityStructuredRelay,
   4430 			reader);
   4431     }
   4432     reader->rngValidErrors = 0;
   4433     reader->rngFullNode = NULL;
   4434     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
   4435     return(0);
   4436 }
   4437 
   4438 /**
   4439  * xmlTextReaderSchemaValidateInternal:
   4440  * @reader:  the xmlTextReaderPtr used
   4441  * @xsd:  the path to a W3C XSD schema or NULL
   4442  * @ctxt: the XML Schema validation context or NULL
   4443  * @options: options (not used yet)
   4444  *
   4445  * Validate the document as it is processed using XML Schema.
   4446  * Activation is only possible before the first Read().
   4447  * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
   4448  *
   4449  * Returns 0 in case the schemas validation could be (de)activated and
   4450  *         -1 in case of error.
   4451  */
   4452 static int
   4453 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
   4454 				    const char *xsd,
   4455 				    xmlSchemaValidCtxtPtr ctxt,
   4456 				    int options ATTRIBUTE_UNUSED)
   4457 {
   4458     if (reader == NULL)
   4459         return(-1);
   4460 
   4461     if ((xsd != NULL) && (ctxt != NULL))
   4462 	return(-1);
   4463 
   4464     if (((xsd != NULL) || (ctxt != NULL)) &&
   4465 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
   4466         (reader->ctxt == NULL)))
   4467 	return(-1);
   4468 
   4469     /* Cleanup previous validation stuff. */
   4470     if (reader->xsdPlug != NULL) {
   4471 	xmlSchemaSAXUnplug(reader->xsdPlug);
   4472 	reader->xsdPlug = NULL;
   4473     }
   4474     if (reader->xsdValidCtxt != NULL) {
   4475 	if (! reader->xsdPreserveCtxt)
   4476 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4477 	reader->xsdValidCtxt = NULL;
   4478     }
   4479     reader->xsdPreserveCtxt = 0;
   4480     if (reader->xsdSchemas != NULL) {
   4481 	xmlSchemaFree(reader->xsdSchemas);
   4482 	reader->xsdSchemas = NULL;
   4483     }
   4484 
   4485     if ((xsd == NULL) && (ctxt == NULL)) {
   4486 	/* We just want to deactivate the validation, so get out. */
   4487 	return(0);
   4488     }
   4489 
   4490     if (xsd != NULL) {
   4491 	xmlSchemaParserCtxtPtr pctxt;
   4492 	/* Parse the schema and create validation environment. */
   4493 	pctxt = xmlSchemaNewParserCtxt(xsd);
   4494 	if (reader->errorFunc != NULL) {
   4495 	    xmlSchemaSetParserErrors(pctxt,
   4496 		xmlTextReaderValidityErrorRelay,
   4497 		xmlTextReaderValidityWarningRelay,
   4498 		reader);
   4499 	}
   4500 	reader->xsdSchemas = xmlSchemaParse(pctxt);
   4501 	xmlSchemaFreeParserCtxt(pctxt);
   4502 	if (reader->xsdSchemas == NULL)
   4503 	    return(-1);
   4504 	reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
   4505 	if (reader->xsdValidCtxt == NULL) {
   4506 	    xmlSchemaFree(reader->xsdSchemas);
   4507 	    reader->xsdSchemas = NULL;
   4508 	    return(-1);
   4509 	}
   4510 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
   4511 	    &(reader->ctxt->sax),
   4512 	    &(reader->ctxt->userData));
   4513 	if (reader->xsdPlug == NULL) {
   4514 	    xmlSchemaFree(reader->xsdSchemas);
   4515 	    reader->xsdSchemas = NULL;
   4516 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4517 	    reader->xsdValidCtxt = NULL;
   4518 	    return(-1);
   4519 	}
   4520     } else {
   4521 	/* Use the given validation context. */
   4522 	reader->xsdValidCtxt = ctxt;
   4523 	reader->xsdPreserveCtxt = 1;
   4524 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
   4525 	    &(reader->ctxt->sax),
   4526 	    &(reader->ctxt->userData));
   4527 	if (reader->xsdPlug == NULL) {
   4528 	    reader->xsdValidCtxt = NULL;
   4529 	    reader->xsdPreserveCtxt = 0;
   4530 	    return(-1);
   4531 	}
   4532     }
   4533     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
   4534                                 xmlTextReaderLocator,
   4535 				(void *) reader);
   4536     /*
   4537     * Redirect the validation context's error channels to use
   4538     * the reader channels.
   4539     * TODO: In case the user provides the validation context we
   4540     *   could make this redirection optional.
   4541     */
   4542     if (reader->errorFunc != NULL) {
   4543 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
   4544 			 xmlTextReaderValidityErrorRelay,
   4545 			 xmlTextReaderValidityWarningRelay,
   4546 			 reader);
   4547     }
   4548 	if (reader->sErrorFunc != NULL) {
   4549 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
   4550 			xmlTextReaderValidityStructuredRelay,
   4551 			reader);
   4552     }
   4553     reader->xsdValidErrors = 0;
   4554     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
   4555     return(0);
   4556 }
   4557 
   4558 /**
   4559  * xmlTextReaderSchemaValidateCtxt:
   4560  * @reader:  the xmlTextReaderPtr used
   4561  * @ctxt: the XML Schema validation context or NULL
   4562  * @options: options (not used yet)
   4563  *
   4564  * Use W3C XSD schema context to validate the document as it is processed.
   4565  * Activation is only possible before the first Read().
   4566  * If @ctxt is NULL, then XML Schema validation is deactivated.
   4567  *
   4568  * Returns 0 in case the schemas validation could be (de)activated and
   4569  *         -1 in case of error.
   4570  */
   4571 int
   4572 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
   4573 				    xmlSchemaValidCtxtPtr ctxt,
   4574 				    int options)
   4575 {
   4576     return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
   4577 }
   4578 
   4579 /**
   4580  * xmlTextReaderSchemaValidate:
   4581  * @reader:  the xmlTextReaderPtr used
   4582  * @xsd:  the path to a W3C XSD schema or NULL
   4583  *
   4584  * Use W3C XSD schema to validate the document as it is processed.
   4585  * Activation is only possible before the first Read().
   4586  * If @xsd is NULL, then XML Schema validation is deactivated.
   4587  *
   4588  * Returns 0 in case the schemas validation could be (de)activated and
   4589  *         -1 in case of error.
   4590  */
   4591 int
   4592 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
   4593 {
   4594     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
   4595 }
   4596 
   4597 /**
   4598  * xmlTextReaderRelaxNGValidateCtxt:
   4599  * @reader:  the xmlTextReaderPtr used
   4600  * @ctxt: the RelaxNG schema validation context or NULL
   4601  * @options: options (not used yet)
   4602  *
   4603  * Use RelaxNG schema context to validate the document as it is processed.
   4604  * Activation is only possible before the first Read().
   4605  * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
   4606  *
   4607  * Returns 0 in case the schemas validation could be (de)activated and
   4608  *         -1 in case of error.
   4609  */
   4610 int
   4611 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
   4612 				 xmlRelaxNGValidCtxtPtr ctxt,
   4613 				 int options)
   4614 {
   4615     return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
   4616 }
   4617 
   4618 /**
   4619  * xmlTextReaderRelaxNGValidate:
   4620  * @reader:  the xmlTextReaderPtr used
   4621  * @rng:  the path to a RelaxNG schema or NULL
   4622  *
   4623  * Use RelaxNG schema to validate the document as it is processed.
   4624  * Activation is only possible before the first Read().
   4625  * If @rng is NULL, then RelaxNG schema validation is deactivated.
   4626  *
   4627  * Returns 0 in case the schemas validation could be (de)activated and
   4628  *         -1 in case of error.
   4629  */
   4630 int
   4631 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
   4632 {
   4633     return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
   4634 }
   4635 
   4636 #endif
   4637 
   4638 /**
   4639  * xmlTextReaderIsNamespaceDecl:
   4640  * @reader: the xmlTextReaderPtr used
   4641  *
   4642  * Determine whether the current node is a namespace declaration
   4643  * rather than a regular attribute.
   4644  *
   4645  * Returns 1 if the current node is a namespace declaration, 0 if it
   4646  * is a regular attribute or other type of node, or -1 in case of
   4647  * error.
   4648  */
   4649 int
   4650 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
   4651     xmlNodePtr node;
   4652     if (reader == NULL)
   4653 	return(-1);
   4654     if (reader->node == NULL)
   4655 	return(-1);
   4656     if (reader->curnode != NULL)
   4657 	node = reader->curnode;
   4658     else
   4659 	node = reader->node;
   4660 
   4661     if (XML_NAMESPACE_DECL == node->type)
   4662 	return(1);
   4663     else
   4664 	return(0);
   4665 }
   4666 
   4667 /**
   4668  * xmlTextReaderConstXmlVersion:
   4669  * @reader:  the xmlTextReaderPtr used
   4670  *
   4671  * Determine the XML version of the document being read.
   4672  *
   4673  * Returns a string containing the XML version of the document or NULL
   4674  * in case of error.  The string is deallocated with the reader.
   4675  */
   4676 const xmlChar *
   4677 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
   4678     xmlDocPtr doc = NULL;
   4679     if (reader == NULL)
   4680 	return(NULL);
   4681     if (reader->doc != NULL)
   4682         doc = reader->doc;
   4683     else if (reader->ctxt != NULL)
   4684 	doc = reader->ctxt->myDoc;
   4685     if (doc == NULL)
   4686 	return(NULL);
   4687 
   4688     if (doc->version == NULL)
   4689 	return(NULL);
   4690     else
   4691       return(CONSTSTR(doc->version));
   4692 }
   4693 
   4694 /**
   4695  * xmlTextReaderStandalone:
   4696  * @reader:  the xmlTextReaderPtr used
   4697  *
   4698  * Determine the standalone status of the document being read.
   4699  *
   4700  * Returns 1 if the document was declared to be standalone, 0 if it
   4701  * was declared to be not standalone, or -1 if the document did not
   4702  * specify its standalone status or in case of error.
   4703  */
   4704 int
   4705 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
   4706     xmlDocPtr doc = NULL;
   4707     if (reader == NULL)
   4708 	return(-1);
   4709     if (reader->doc != NULL)
   4710         doc = reader->doc;
   4711     else if (reader->ctxt != NULL)
   4712 	doc = reader->ctxt->myDoc;
   4713     if (doc == NULL)
   4714 	return(-1);
   4715 
   4716     return(doc->standalone);
   4717 }
   4718 
   4719 /************************************************************************
   4720  *									*
   4721  *			Error Handling Extensions                       *
   4722  *									*
   4723  ************************************************************************/
   4724 
   4725 /* helper to build a xmlMalloc'ed string from a format and va_list */
   4726 static char *
   4727 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
   4728     int size = 0;
   4729     int chars;
   4730     char *larger;
   4731     char *str = NULL;
   4732     va_list aq;
   4733 
   4734     while (1) {
   4735         VA_COPY(aq, ap);
   4736         chars = vsnprintf(str, size, msg, aq);
   4737         va_end(aq);
   4738         if (chars < 0) {
   4739 	    xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
   4740 	    if (str)
   4741 		xmlFree(str);
   4742 	    return NULL;
   4743 	}
   4744 	if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
   4745             break;
   4746         if (chars < MAX_ERR_MSG_SIZE)
   4747 	size = chars + 1;
   4748 	else
   4749 		size = MAX_ERR_MSG_SIZE;
   4750         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
   4751 	    xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
   4752 	    if (str)
   4753                 xmlFree(str);
   4754             return NULL;
   4755         }
   4756         str = larger;
   4757     }
   4758 
   4759     return str;
   4760 }
   4761 
   4762 /**
   4763  * xmlTextReaderLocatorLineNumber:
   4764  * @locator: the xmlTextReaderLocatorPtr used
   4765  *
   4766  * Obtain the line number for the given locator.
   4767  *
   4768  * Returns the line number or -1 in case of error.
   4769  */
   4770 int
   4771 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
   4772     /* we know that locator is a xmlParserCtxtPtr */
   4773     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
   4774     int ret = -1;
   4775 
   4776     if (locator == NULL)
   4777         return(-1);
   4778     if (ctx->node != NULL) {
   4779 	ret = xmlGetLineNo(ctx->node);
   4780     }
   4781     else {
   4782 	/* inspired from error.c */
   4783 	xmlParserInputPtr input;
   4784 	input = ctx->input;
   4785 	if ((input->filename == NULL) && (ctx->inputNr > 1))
   4786 	    input = ctx->inputTab[ctx->inputNr - 2];
   4787 	if (input != NULL) {
   4788 	    ret = input->line;
   4789 	}
   4790 	else {
   4791 	    ret = -1;
   4792 	}
   4793     }
   4794 
   4795     return ret;
   4796 }
   4797 
   4798 /**
   4799  * xmlTextReaderLocatorBaseURI:
   4800  * @locator: the xmlTextReaderLocatorPtr used
   4801  *
   4802  * Obtain the base URI for the given locator.
   4803  *
   4804  * Returns the base URI or NULL in case of error,
   4805  *    if non NULL it need to be freed by the caller.
   4806  */
   4807 xmlChar *
   4808 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
   4809     /* we know that locator is a xmlParserCtxtPtr */
   4810     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
   4811     xmlChar *ret = NULL;
   4812 
   4813     if (locator == NULL)
   4814         return(NULL);
   4815     if (ctx->node != NULL) {
   4816 	ret = xmlNodeGetBase(NULL,ctx->node);
   4817     }
   4818     else {
   4819 	/* inspired from error.c */
   4820 	xmlParserInputPtr input;
   4821 	input = ctx->input;
   4822 	if ((input->filename == NULL) && (ctx->inputNr > 1))
   4823 	    input = ctx->inputTab[ctx->inputNr - 2];
   4824 	if (input != NULL) {
   4825 	    ret = xmlStrdup(BAD_CAST input->filename);
   4826 	}
   4827 	else {
   4828 	    ret = NULL;
   4829 	}
   4830     }
   4831 
   4832     return ret;
   4833 }
   4834 
   4835 static void
   4836 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
   4837                           char *str)
   4838 {
   4839     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
   4840 
   4841     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
   4842 
   4843     if (str != NULL) {
   4844         if (reader->errorFunc)
   4845             reader->errorFunc(reader->errorFuncArg, str, severity,
   4846                               (xmlTextReaderLocatorPtr) ctx);
   4847         xmlFree(str);
   4848     }
   4849 }
   4850 
   4851 static void
   4852 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
   4853 {
   4854     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
   4855 
   4856     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
   4857 
   4858     if (error && reader->sErrorFunc) {
   4859         reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
   4860     }
   4861 }
   4862 
   4863 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
   4864 xmlTextReaderError(void *ctxt, const char *msg, ...)
   4865 {
   4866     va_list ap;
   4867 
   4868     va_start(ap, msg);
   4869     xmlTextReaderGenericError(ctxt,
   4870                               XML_PARSER_SEVERITY_ERROR,
   4871                               xmlTextReaderBuildMessage(msg, ap));
   4872     va_end(ap);
   4873 
   4874 }
   4875 
   4876 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
   4877 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
   4878 {
   4879     va_list ap;
   4880 
   4881     va_start(ap, msg);
   4882     xmlTextReaderGenericError(ctxt,
   4883                               XML_PARSER_SEVERITY_WARNING,
   4884                               xmlTextReaderBuildMessage(msg, ap));
   4885     va_end(ap);
   4886 }
   4887 
   4888 static void XMLCDECL
   4889 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
   4890 {
   4891     va_list ap;
   4892 
   4893     int len = xmlStrlen((const xmlChar *) msg);
   4894 
   4895     if ((len > 1) && (msg[len - 2] != ':')) {
   4896         /*
   4897          * some callbacks only report locator information:
   4898          * skip them (mimicking behaviour in error.c)
   4899          */
   4900         va_start(ap, msg);
   4901         xmlTextReaderGenericError(ctxt,
   4902                                   XML_PARSER_SEVERITY_VALIDITY_ERROR,
   4903                                   xmlTextReaderBuildMessage(msg, ap));
   4904         va_end(ap);
   4905     }
   4906 }
   4907 
   4908 static void XMLCDECL
   4909 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
   4910 {
   4911     va_list ap;
   4912 
   4913     int len = xmlStrlen((const xmlChar *) msg);
   4914 
   4915     if ((len != 0) && (msg[len - 1] != ':')) {
   4916         /*
   4917          * some callbacks only report locator information:
   4918          * skip them (mimicking behaviour in error.c)
   4919          */
   4920         va_start(ap, msg);
   4921         xmlTextReaderGenericError(ctxt,
   4922                                   XML_PARSER_SEVERITY_VALIDITY_WARNING,
   4923                                   xmlTextReaderBuildMessage(msg, ap));
   4924         va_end(ap);
   4925     }
   4926 }
   4927 
   4928 /**
   4929  * xmlTextReaderSetErrorHandler:
   4930  * @reader:  the xmlTextReaderPtr used
   4931  * @f:	the callback function to call on error and warnings
   4932  * @arg:    a user argument to pass to the callback function
   4933  *
   4934  * Register a callback function that will be called on error and warnings.
   4935  *
   4936  * If @f is NULL, the default error and warning handlers are restored.
   4937  */
   4938 void
   4939 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
   4940                              xmlTextReaderErrorFunc f, void *arg)
   4941 {
   4942     if (f != NULL) {
   4943         reader->ctxt->sax->error = xmlTextReaderError;
   4944         reader->ctxt->sax->serror = NULL;
   4945         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
   4946         reader->ctxt->sax->warning = xmlTextReaderWarning;
   4947         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
   4948         reader->errorFunc = f;
   4949         reader->sErrorFunc = NULL;
   4950         reader->errorFuncArg = arg;
   4951 #ifdef LIBXML_SCHEMAS_ENABLED
   4952         if (reader->rngValidCtxt) {
   4953             xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
   4954                                      xmlTextReaderValidityErrorRelay,
   4955                                      xmlTextReaderValidityWarningRelay,
   4956                                      reader);
   4957             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
   4958                                                reader);
   4959         }
   4960         if (reader->xsdValidCtxt) {
   4961             xmlSchemaSetValidErrors(reader->xsdValidCtxt,
   4962                                     xmlTextReaderValidityErrorRelay,
   4963                                     xmlTextReaderValidityWarningRelay,
   4964                                     reader);
   4965             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
   4966                                               reader);
   4967         }
   4968 #endif
   4969     } else {
   4970         /* restore defaults */
   4971         reader->ctxt->sax->error = xmlParserError;
   4972         reader->ctxt->vctxt.error = xmlParserValidityError;
   4973         reader->ctxt->sax->warning = xmlParserWarning;
   4974         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
   4975         reader->errorFunc = NULL;
   4976         reader->sErrorFunc = NULL;
   4977         reader->errorFuncArg = NULL;
   4978 #ifdef LIBXML_SCHEMAS_ENABLED
   4979         if (reader->rngValidCtxt) {
   4980             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
   4981                                      reader);
   4982             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
   4983                                                reader);
   4984         }
   4985         if (reader->xsdValidCtxt) {
   4986             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
   4987                                     reader);
   4988             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
   4989                                               reader);
   4990         }
   4991 #endif
   4992     }
   4993 }
   4994 
   4995 /**
   4996 * xmlTextReaderSetStructuredErrorHandler:
   4997  * @reader:  the xmlTextReaderPtr used
   4998  * @f:	the callback function to call on error and warnings
   4999  * @arg:    a user argument to pass to the callback function
   5000  *
   5001  * Register a callback function that will be called on error and warnings.
   5002  *
   5003  * If @f is NULL, the default error and warning handlers are restored.
   5004  */
   5005 void
   5006 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
   5007                                        xmlStructuredErrorFunc f, void *arg)
   5008 {
   5009     if (f != NULL) {
   5010         reader->ctxt->sax->error = NULL;
   5011         reader->ctxt->sax->serror = xmlTextReaderStructuredError;
   5012         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
   5013         reader->ctxt->sax->warning = xmlTextReaderWarning;
   5014         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
   5015         reader->sErrorFunc = f;
   5016         reader->errorFunc = NULL;
   5017         reader->errorFuncArg = arg;
   5018 #ifdef LIBXML_SCHEMAS_ENABLED
   5019         if (reader->rngValidCtxt) {
   5020             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
   5021                                      reader);
   5022             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   5023                                         xmlTextReaderValidityStructuredRelay,
   5024                                                reader);
   5025         }
   5026         if (reader->xsdValidCtxt) {
   5027             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
   5028                                     reader);
   5029             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
   5030                                        xmlTextReaderValidityStructuredRelay,
   5031                                               reader);
   5032         }
   5033 #endif
   5034     } else {
   5035         /* restore defaults */
   5036         reader->ctxt->sax->error = xmlParserError;
   5037         reader->ctxt->sax->serror = NULL;
   5038         reader->ctxt->vctxt.error = xmlParserValidityError;
   5039         reader->ctxt->sax->warning = xmlParserWarning;
   5040         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
   5041         reader->errorFunc = NULL;
   5042         reader->sErrorFunc = NULL;
   5043         reader->errorFuncArg = NULL;
   5044 #ifdef LIBXML_SCHEMAS_ENABLED
   5045         if (reader->rngValidCtxt) {
   5046             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
   5047                                      reader);
   5048             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
   5049                                                reader);
   5050         }
   5051         if (reader->xsdValidCtxt) {
   5052             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
   5053                                     reader);
   5054             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
   5055                                               reader);
   5056         }
   5057 #endif
   5058     }
   5059 }
   5060 
   5061 /**
   5062  * xmlTextReaderIsValid:
   5063  * @reader:  the xmlTextReaderPtr used
   5064  *
   5065  * Retrieve the validity status from the parser context
   5066  *
   5067  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
   5068  */
   5069 int
   5070 xmlTextReaderIsValid(xmlTextReaderPtr reader)
   5071 {
   5072     if (reader == NULL)
   5073         return (-1);
   5074 #ifdef LIBXML_SCHEMAS_ENABLED
   5075     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
   5076         return (reader->rngValidErrors == 0);
   5077     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
   5078         return (reader->xsdValidErrors == 0);
   5079 #endif
   5080     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
   5081         return (reader->ctxt->valid);
   5082     return (0);
   5083 }
   5084 
   5085 /**
   5086  * xmlTextReaderGetErrorHandler:
   5087  * @reader:  the xmlTextReaderPtr used
   5088  * @f:	the callback function or NULL is no callback has been registered
   5089  * @arg:    a user argument
   5090  *
   5091  * Retrieve the error callback function and user argument.
   5092  */
   5093 void
   5094 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
   5095                              xmlTextReaderErrorFunc * f, void **arg)
   5096 {
   5097     if (f != NULL)
   5098         *f = reader->errorFunc;
   5099     if (arg != NULL)
   5100         *arg = reader->errorFuncArg;
   5101 }
   5102 /************************************************************************
   5103  *									*
   5104  *	New set (2.6.0) of simpler and more flexible APIs		*
   5105  *									*
   5106  ************************************************************************/
   5107 
   5108 /**
   5109  * xmlTextReaderSetup:
   5110  * @reader:  an XML reader
   5111  * @input: xmlParserInputBufferPtr used to feed the reader, will
   5112  *         be destroyed with it.
   5113  * @URL:  the base URL to use for the document
   5114  * @encoding:  the document encoding, or NULL
   5115  * @options:  a combination of xmlParserOption
   5116  *
   5117  * Setup an XML reader with new options
   5118  *
   5119  * Returns 0 in case of success and -1 in case of error.
   5120  */
   5121 int
   5122 xmlTextReaderSetup(xmlTextReaderPtr reader,
   5123                    xmlParserInputBufferPtr input, const char *URL,
   5124                    const char *encoding, int options)
   5125 {
   5126     if (reader == NULL) {
   5127         if (input != NULL)
   5128 	    xmlFreeParserInputBuffer(input);
   5129         return (-1);
   5130     }
   5131 
   5132     /*
   5133      * we force the generation of compact text nodes on the reader
   5134      * since usr applications should never modify the tree
   5135      */
   5136     options |= XML_PARSE_COMPACT;
   5137 
   5138     reader->doc = NULL;
   5139     reader->entNr = 0;
   5140     reader->parserFlags = options;
   5141     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
   5142     if ((input != NULL) && (reader->input != NULL) &&
   5143         (reader->allocs & XML_TEXTREADER_INPUT)) {
   5144 	xmlFreeParserInputBuffer(reader->input);
   5145 	reader->input = NULL;
   5146 	reader->allocs -= XML_TEXTREADER_INPUT;
   5147     }
   5148     if (input != NULL) {
   5149 	reader->input = input;
   5150 	reader->allocs |= XML_TEXTREADER_INPUT;
   5151     }
   5152     if (reader->buffer == NULL)
   5153         reader->buffer = xmlBufCreateSize(100);
   5154     if (reader->buffer == NULL) {
   5155         xmlGenericError(xmlGenericErrorContext,
   5156                         "xmlTextReaderSetup : malloc failed\n");
   5157         return (-1);
   5158     }
   5159     /* no operation on a reader should require a huge buffer */
   5160     xmlBufSetAllocationScheme(reader->buffer,
   5161 			      XML_BUFFER_ALLOC_BOUNDED);
   5162     if (reader->sax == NULL)
   5163 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
   5164     if (reader->sax == NULL) {
   5165         xmlGenericError(xmlGenericErrorContext,
   5166                         "xmlTextReaderSetup : malloc failed\n");
   5167         return (-1);
   5168     }
   5169     xmlSAXVersion(reader->sax, 2);
   5170     reader->startElement = reader->sax->startElement;
   5171     reader->sax->startElement = xmlTextReaderStartElement;
   5172     reader->endElement = reader->sax->endElement;
   5173     reader->sax->endElement = xmlTextReaderEndElement;
   5174 #ifdef LIBXML_SAX1_ENABLED
   5175     if (reader->sax->initialized == XML_SAX2_MAGIC) {
   5176 #endif /* LIBXML_SAX1_ENABLED */
   5177         reader->startElementNs = reader->sax->startElementNs;
   5178         reader->sax->startElementNs = xmlTextReaderStartElementNs;
   5179         reader->endElementNs = reader->sax->endElementNs;
   5180         reader->sax->endElementNs = xmlTextReaderEndElementNs;
   5181 #ifdef LIBXML_SAX1_ENABLED
   5182     } else {
   5183         reader->startElementNs = NULL;
   5184         reader->endElementNs = NULL;
   5185     }
   5186 #endif /* LIBXML_SAX1_ENABLED */
   5187     reader->characters = reader->sax->characters;
   5188     reader->sax->characters = xmlTextReaderCharacters;
   5189     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
   5190     reader->cdataBlock = reader->sax->cdataBlock;
   5191     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
   5192 
   5193     reader->mode = XML_TEXTREADER_MODE_INITIAL;
   5194     reader->node = NULL;
   5195     reader->curnode = NULL;
   5196     if (input != NULL) {
   5197         if (xmlBufUse(reader->input->buffer) < 4) {
   5198             xmlParserInputBufferRead(input, 4);
   5199         }
   5200         if (reader->ctxt == NULL) {
   5201             if (xmlBufUse(reader->input->buffer) >= 4) {
   5202                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
   5203 		       (const char *) xmlBufContent(reader->input->buffer),
   5204                                       4, URL);
   5205                 reader->base = 0;
   5206                 reader->cur = 4;
   5207             } else {
   5208                 reader->ctxt =
   5209                     xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
   5210                 reader->base = 0;
   5211                 reader->cur = 0;
   5212             }
   5213         } else {
   5214 	    xmlParserInputPtr inputStream;
   5215 	    xmlParserInputBufferPtr buf;
   5216 	    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
   5217 
   5218 	    xmlCtxtReset(reader->ctxt);
   5219 	    buf = xmlAllocParserInputBuffer(enc);
   5220 	    if (buf == NULL) return(-1);
   5221 	    inputStream = xmlNewInputStream(reader->ctxt);
   5222 	    if (inputStream == NULL) {
   5223 		xmlFreeParserInputBuffer(buf);
   5224 		return(-1);
   5225 	    }
   5226 
   5227 	    if (URL == NULL)
   5228 		inputStream->filename = NULL;
   5229 	    else
   5230 		inputStream->filename = (char *)
   5231 		    xmlCanonicPath((const xmlChar *) URL);
   5232 	    inputStream->buf = buf;
   5233             xmlBufResetInput(buf->buffer, inputStream);
   5234 
   5235 	    inputPush(reader->ctxt, inputStream);
   5236 	    reader->cur = 0;
   5237 	}
   5238         if (reader->ctxt == NULL) {
   5239             xmlGenericError(xmlGenericErrorContext,
   5240                             "xmlTextReaderSetup : malloc failed\n");
   5241             return (-1);
   5242         }
   5243     }
   5244     if (reader->dict != NULL) {
   5245         if (reader->ctxt->dict != NULL) {
   5246 	    if (reader->dict != reader->ctxt->dict) {
   5247 		xmlDictFree(reader->dict);
   5248 		reader->dict = reader->ctxt->dict;
   5249 	    }
   5250 	} else {
   5251 	    reader->ctxt->dict = reader->dict;
   5252 	}
   5253     } else {
   5254 	if (reader->ctxt->dict == NULL)
   5255 	    reader->ctxt->dict = xmlDictCreate();
   5256         reader->dict = reader->ctxt->dict;
   5257     }
   5258     reader->ctxt->_private = reader;
   5259     reader->ctxt->linenumbers = 1;
   5260     reader->ctxt->dictNames = 1;
   5261     /*
   5262      * use the parser dictionary to allocate all elements and attributes names
   5263      */
   5264     reader->ctxt->docdict = 1;
   5265     reader->ctxt->parseMode = XML_PARSE_READER;
   5266 
   5267 #ifdef LIBXML_XINCLUDE_ENABLED
   5268     if (reader->xincctxt != NULL) {
   5269 	xmlXIncludeFreeContext(reader->xincctxt);
   5270 	reader->xincctxt = NULL;
   5271     }
   5272     if (options & XML_PARSE_XINCLUDE) {
   5273         reader->xinclude = 1;
   5274 	reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
   5275 	options -= XML_PARSE_XINCLUDE;
   5276     } else
   5277         reader->xinclude = 0;
   5278     reader->in_xinclude = 0;
   5279 #endif
   5280 #ifdef LIBXML_PATTERN_ENABLED
   5281     if (reader->patternTab == NULL) {
   5282         reader->patternNr = 0;
   5283 	reader->patternMax = 0;
   5284     }
   5285     while (reader->patternNr > 0) {
   5286         reader->patternNr--;
   5287 	if (reader->patternTab[reader->patternNr] != NULL) {
   5288 	    xmlFreePattern(reader->patternTab[reader->patternNr]);
   5289             reader->patternTab[reader->patternNr] = NULL;
   5290 	}
   5291     }
   5292 #endif
   5293 
   5294     if (options & XML_PARSE_DTDVALID)
   5295         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
   5296 
   5297     xmlCtxtUseOptions(reader->ctxt, options);
   5298     if (encoding != NULL) {
   5299         xmlCharEncodingHandlerPtr hdlr;
   5300 
   5301         hdlr = xmlFindCharEncodingHandler(encoding);
   5302         if (hdlr != NULL)
   5303             xmlSwitchToEncoding(reader->ctxt, hdlr);
   5304     }
   5305     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
   5306         (reader->ctxt->input->filename == NULL))
   5307         reader->ctxt->input->filename = (char *)
   5308             xmlStrdup((const xmlChar *) URL);
   5309 
   5310     reader->doc = NULL;
   5311 
   5312     return (0);
   5313 }
   5314 
   5315 /**
   5316  * xmlTextReaderByteConsumed:
   5317  * @reader: an XML reader
   5318  *
   5319  * This function provides the current index of the parser used
   5320  * by the reader, relative to the start of the current entity.
   5321  * This function actually just wraps a call to xmlBytesConsumed()
   5322  * for the parser context associated with the reader.
   5323  * See xmlBytesConsumed() for more information.
   5324  *
   5325  * Returns the index in bytes from the beginning of the entity or -1
   5326  *         in case the index could not be computed.
   5327  */
   5328 long
   5329 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
   5330     if ((reader == NULL) || (reader->ctxt == NULL))
   5331         return(-1);
   5332     return(xmlByteConsumed(reader->ctxt));
   5333 }
   5334 
   5335 
   5336 /**
   5337  * xmlReaderWalker:
   5338  * @doc:  a preparsed document
   5339  *
   5340  * Create an xmltextReader for a preparsed document.
   5341  *
   5342  * Returns the new reader or NULL in case of error.
   5343  */
   5344 xmlTextReaderPtr
   5345 xmlReaderWalker(xmlDocPtr doc)
   5346 {
   5347     xmlTextReaderPtr ret;
   5348 
   5349     if (doc == NULL)
   5350         return(NULL);
   5351 
   5352     ret = xmlMalloc(sizeof(xmlTextReader));
   5353     if (ret == NULL) {
   5354         xmlGenericError(xmlGenericErrorContext,
   5355 		"xmlNewTextReader : malloc failed\n");
   5356 	return(NULL);
   5357     }
   5358     memset(ret, 0, sizeof(xmlTextReader));
   5359     ret->entNr = 0;
   5360     ret->input = NULL;
   5361     ret->mode = XML_TEXTREADER_MODE_INITIAL;
   5362     ret->node = NULL;
   5363     ret->curnode = NULL;
   5364     ret->base = 0;
   5365     ret->cur = 0;
   5366     ret->allocs = XML_TEXTREADER_CTXT;
   5367     ret->doc = doc;
   5368     ret->state = XML_TEXTREADER_START;
   5369     ret->dict = xmlDictCreate();
   5370     return(ret);
   5371 }
   5372 
   5373 /**
   5374  * xmlReaderForDoc:
   5375  * @cur:  a pointer to a zero terminated string
   5376  * @URL:  the base URL to use for the document
   5377  * @encoding:  the document encoding, or NULL
   5378  * @options:  a combination of xmlParserOption
   5379  *
   5380  * Create an xmltextReader for an XML in-memory document.
   5381  * The parsing flags @options are a combination of xmlParserOption.
   5382  *
   5383  * Returns the new reader or NULL in case of error.
   5384  */
   5385 xmlTextReaderPtr
   5386 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
   5387                 int options)
   5388 {
   5389     int len;
   5390 
   5391     if (cur == NULL)
   5392         return (NULL);
   5393     len = xmlStrlen(cur);
   5394 
   5395     return (xmlReaderForMemory
   5396             ((const char *) cur, len, URL, encoding, options));
   5397 }
   5398 
   5399 /**
   5400  * xmlReaderForFile:
   5401  * @filename:  a file or URL
   5402  * @encoding:  the document encoding, or NULL
   5403  * @options:  a combination of xmlParserOption
   5404  *
   5405  * parse an XML file from the filesystem or the network.
   5406  * The parsing flags @options are a combination of xmlParserOption.
   5407  *
   5408  * Returns the new reader or NULL in case of error.
   5409  */
   5410 xmlTextReaderPtr
   5411 xmlReaderForFile(const char *filename, const char *encoding, int options)
   5412 {
   5413     xmlTextReaderPtr reader;
   5414 
   5415     reader = xmlNewTextReaderFilename(filename);
   5416     if (reader == NULL)
   5417         return (NULL);
   5418     xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
   5419     return (reader);
   5420 }
   5421 
   5422 /**
   5423  * xmlReaderForMemory:
   5424  * @buffer:  a pointer to a char array
   5425  * @size:  the size of the array
   5426  * @URL:  the base URL to use for the document
   5427  * @encoding:  the document encoding, or NULL
   5428  * @options:  a combination of xmlParserOption
   5429  *
   5430  * Create an xmltextReader for an XML in-memory document.
   5431  * The parsing flags @options are a combination of xmlParserOption.
   5432  *
   5433  * Returns the new reader or NULL in case of error.
   5434  */
   5435 xmlTextReaderPtr
   5436 xmlReaderForMemory(const char *buffer, int size, const char *URL,
   5437                    const char *encoding, int options)
   5438 {
   5439     xmlTextReaderPtr reader;
   5440     xmlParserInputBufferPtr buf;
   5441 
   5442     buf = xmlParserInputBufferCreateStatic(buffer, size,
   5443                                       XML_CHAR_ENCODING_NONE);
   5444     if (buf == NULL) {
   5445         return (NULL);
   5446     }
   5447     reader = xmlNewTextReader(buf, URL);
   5448     if (reader == NULL) {
   5449         xmlFreeParserInputBuffer(buf);
   5450         return (NULL);
   5451     }
   5452     reader->allocs |= XML_TEXTREADER_INPUT;
   5453     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
   5454     return (reader);
   5455 }
   5456 
   5457 /**
   5458  * xmlReaderForFd:
   5459  * @fd:  an open file descriptor
   5460  * @URL:  the base URL to use for the document
   5461  * @encoding:  the document encoding, or NULL
   5462  * @options:  a combination of xmlParserOption
   5463  *
   5464  * Create an xmltextReader for an XML from a file descriptor.
   5465  * The parsing flags @options are a combination of xmlParserOption.
   5466  * NOTE that the file descriptor will not be closed when the
   5467  *      reader is closed or reset.
   5468  *
   5469  * Returns the new reader or NULL in case of error.
   5470  */
   5471 xmlTextReaderPtr
   5472 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
   5473 {
   5474     xmlTextReaderPtr reader;
   5475     xmlParserInputBufferPtr input;
   5476 
   5477     if (fd < 0)
   5478         return (NULL);
   5479 
   5480     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
   5481     if (input == NULL)
   5482         return (NULL);
   5483     input->closecallback = NULL;
   5484     reader = xmlNewTextReader(input, URL);
   5485     if (reader == NULL) {
   5486         xmlFreeParserInputBuffer(input);
   5487         return (NULL);
   5488     }
   5489     reader->allocs |= XML_TEXTREADER_INPUT;
   5490     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
   5491     return (reader);
   5492 }
   5493 
   5494 /**
   5495  * xmlReaderForIO:
   5496  * @ioread:  an I/O read function
   5497  * @ioclose:  an I/O close function
   5498  * @ioctx:  an I/O handler
   5499  * @URL:  the base URL to use for the document
   5500  * @encoding:  the document encoding, or NULL
   5501  * @options:  a combination of xmlParserOption
   5502  *
   5503  * Create an xmltextReader for an XML document from I/O functions and source.
   5504  * The parsing flags @options are a combination of xmlParserOption.
   5505  *
   5506  * Returns the new reader or NULL in case of error.
   5507  */
   5508 xmlTextReaderPtr
   5509 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
   5510                void *ioctx, const char *URL, const char *encoding,
   5511                int options)
   5512 {
   5513     xmlTextReaderPtr reader;
   5514     xmlParserInputBufferPtr input;
   5515 
   5516     if (ioread == NULL)
   5517         return (NULL);
   5518 
   5519     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
   5520                                          XML_CHAR_ENCODING_NONE);
   5521     if (input == NULL) {
   5522         if (ioclose != NULL)
   5523             ioclose(ioctx);
   5524         return (NULL);
   5525     }
   5526     reader = xmlNewTextReader(input, URL);
   5527     if (reader == NULL) {
   5528         xmlFreeParserInputBuffer(input);
   5529         return (NULL);
   5530     }
   5531     reader->allocs |= XML_TEXTREADER_INPUT;
   5532     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
   5533     return (reader);
   5534 }
   5535 
   5536 /**
   5537  * xmlReaderNewWalker:
   5538  * @reader:  an XML reader
   5539  * @doc:  a preparsed document
   5540  *
   5541  * Setup an xmltextReader to parse a preparsed XML document.
   5542  * This reuses the existing @reader xmlTextReader.
   5543  *
   5544  * Returns 0 in case of success and -1 in case of error
   5545  */
   5546 int
   5547 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
   5548 {
   5549     if (doc == NULL)
   5550         return (-1);
   5551     if (reader == NULL)
   5552         return (-1);
   5553 
   5554     if (reader->input != NULL) {
   5555         xmlFreeParserInputBuffer(reader->input);
   5556     }
   5557     if (reader->ctxt != NULL) {
   5558 	xmlCtxtReset(reader->ctxt);
   5559     }
   5560 
   5561     reader->entNr = 0;
   5562     reader->input = NULL;
   5563     reader->mode = XML_TEXTREADER_MODE_INITIAL;
   5564     reader->node = NULL;
   5565     reader->curnode = NULL;
   5566     reader->base = 0;
   5567     reader->cur = 0;
   5568     reader->allocs = XML_TEXTREADER_CTXT;
   5569     reader->doc = doc;
   5570     reader->state = XML_TEXTREADER_START;
   5571     if (reader->dict == NULL) {
   5572         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
   5573 	    reader->dict = reader->ctxt->dict;
   5574 	else
   5575 	    reader->dict = xmlDictCreate();
   5576     }
   5577     return(0);
   5578 }
   5579 
   5580 /**
   5581  * xmlReaderNewDoc:
   5582  * @reader:  an XML reader
   5583  * @cur:  a pointer to a zero terminated string
   5584  * @URL:  the base URL to use for the document
   5585  * @encoding:  the document encoding, or NULL
   5586  * @options:  a combination of xmlParserOption
   5587  *
   5588  * Setup an xmltextReader to parse an XML in-memory document.
   5589  * The parsing flags @options are a combination of xmlParserOption.
   5590  * This reuses the existing @reader xmlTextReader.
   5591  *
   5592  * Returns 0 in case of success and -1 in case of error
   5593  */
   5594 int
   5595 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
   5596                 const char *URL, const char *encoding, int options)
   5597 {
   5598 
   5599     int len;
   5600 
   5601     if (cur == NULL)
   5602         return (-1);
   5603     if (reader == NULL)
   5604         return (-1);
   5605 
   5606     len = xmlStrlen(cur);
   5607     return (xmlReaderNewMemory(reader, (const char *)cur, len,
   5608                                URL, encoding, options));
   5609 }
   5610 
   5611 /**
   5612  * xmlReaderNewFile:
   5613  * @reader:  an XML reader
   5614  * @filename:  a file or URL
   5615  * @encoding:  the document encoding, or NULL
   5616  * @options:  a combination of xmlParserOption
   5617  *
   5618  * parse an XML file from the filesystem or the network.
   5619  * The parsing flags @options are a combination of xmlParserOption.
   5620  * This reuses the existing @reader xmlTextReader.
   5621  *
   5622  * Returns 0 in case of success and -1 in case of error
   5623  */
   5624 int
   5625 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
   5626                  const char *encoding, int options)
   5627 {
   5628     xmlParserInputBufferPtr input;
   5629 
   5630     if (filename == NULL)
   5631         return (-1);
   5632     if (reader == NULL)
   5633         return (-1);
   5634 
   5635     input =
   5636         xmlParserInputBufferCreateFilename(filename,
   5637                                            XML_CHAR_ENCODING_NONE);
   5638     if (input == NULL)
   5639         return (-1);
   5640     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
   5641 }
   5642 
   5643 /**
   5644  * xmlReaderNewMemory:
   5645  * @reader:  an XML reader
   5646  * @buffer:  a pointer to a char array
   5647  * @size:  the size of the array
   5648  * @URL:  the base URL to use for the document
   5649  * @encoding:  the document encoding, or NULL
   5650  * @options:  a combination of xmlParserOption
   5651  *
   5652  * Setup an xmltextReader to parse an XML in-memory document.
   5653  * The parsing flags @options are a combination of xmlParserOption.
   5654  * This reuses the existing @reader xmlTextReader.
   5655  *
   5656  * Returns 0 in case of success and -1 in case of error
   5657  */
   5658 int
   5659 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
   5660                    const char *URL, const char *encoding, int options)
   5661 {
   5662     xmlParserInputBufferPtr input;
   5663 
   5664     if (reader == NULL)
   5665         return (-1);
   5666     if (buffer == NULL)
   5667         return (-1);
   5668 
   5669     input = xmlParserInputBufferCreateStatic(buffer, size,
   5670                                       XML_CHAR_ENCODING_NONE);
   5671     if (input == NULL) {
   5672         return (-1);
   5673     }
   5674     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
   5675 }
   5676 
   5677 /**
   5678  * xmlReaderNewFd:
   5679  * @reader:  an XML reader
   5680  * @fd:  an open file descriptor
   5681  * @URL:  the base URL to use for the document
   5682  * @encoding:  the document encoding, or NULL
   5683  * @options:  a combination of xmlParserOption
   5684  *
   5685  * Setup an xmltextReader to parse an XML from a file descriptor.
   5686  * NOTE that the file descriptor will not be closed when the
   5687  *      reader is closed or reset.
   5688  * The parsing flags @options are a combination of xmlParserOption.
   5689  * This reuses the existing @reader xmlTextReader.
   5690  *
   5691  * Returns 0 in case of success and -1 in case of error
   5692  */
   5693 int
   5694 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
   5695                const char *URL, const char *encoding, int options)
   5696 {
   5697     xmlParserInputBufferPtr input;
   5698 
   5699     if (fd < 0)
   5700         return (-1);
   5701     if (reader == NULL)
   5702         return (-1);
   5703 
   5704     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
   5705     if (input == NULL)
   5706         return (-1);
   5707     input->closecallback = NULL;
   5708     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
   5709 }
   5710 
   5711 /**
   5712  * xmlReaderNewIO:
   5713  * @reader:  an XML reader
   5714  * @ioread:  an I/O read function
   5715  * @ioclose:  an I/O close function
   5716  * @ioctx:  an I/O handler
   5717  * @URL:  the base URL to use for the document
   5718  * @encoding:  the document encoding, or NULL
   5719  * @options:  a combination of xmlParserOption
   5720  *
   5721  * Setup an xmltextReader to parse an XML document from I/O functions
   5722  * and source.
   5723  * The parsing flags @options are a combination of xmlParserOption.
   5724  * This reuses the existing @reader xmlTextReader.
   5725  *
   5726  * Returns 0 in case of success and -1 in case of error
   5727  */
   5728 int
   5729 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
   5730                xmlInputCloseCallback ioclose, void *ioctx,
   5731                const char *URL, const char *encoding, int options)
   5732 {
   5733     xmlParserInputBufferPtr input;
   5734 
   5735     if (ioread == NULL)
   5736         return (-1);
   5737     if (reader == NULL)
   5738         return (-1);
   5739 
   5740     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
   5741                                          XML_CHAR_ENCODING_NONE);
   5742     if (input == NULL) {
   5743         if (ioclose != NULL)
   5744             ioclose(ioctx);
   5745         return (-1);
   5746     }
   5747     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
   5748 }
   5749 
   5750 /************************************************************************
   5751  *									*
   5752  *			Utilities					*
   5753  *									*
   5754  ************************************************************************/
   5755 #ifdef NOT_USED_YET
   5756 
   5757 /**
   5758  * xmlBase64Decode:
   5759  * @in:  the input buffer
   5760  * @inlen:  the size of the input (in), the size read from it (out)
   5761  * @to:  the output buffer
   5762  * @tolen:  the size of the output (in), the size written to (out)
   5763  *
   5764  * Base64 decoder, reads from @in and save in @to
   5765  * TODO: tell jody when this is actually exported
   5766  *
   5767  * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
   5768  *         2 if there wasn't enough space on the output or -1 in case of error.
   5769  */
   5770 static int
   5771 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
   5772                 unsigned char *to, unsigned long *tolen)
   5773 {
   5774     unsigned long incur;        /* current index in in[] */
   5775 
   5776     unsigned long inblk;        /* last block index in in[] */
   5777 
   5778     unsigned long outcur;       /* current index in out[] */
   5779 
   5780     unsigned long inmax;        /* size of in[] */
   5781 
   5782     unsigned long outmax;       /* size of out[] */
   5783 
   5784     unsigned char cur;          /* the current value read from in[] */
   5785 
   5786     unsigned char intmp[4], outtmp[4];  /* temporary buffers for the convert */
   5787 
   5788     int nbintmp;                /* number of byte in intmp[] */
   5789 
   5790     int is_ignore;              /* cur should be ignored */
   5791 
   5792     int is_end = 0;             /* the end of the base64 was found */
   5793 
   5794     int retval = 1;
   5795 
   5796     int i;
   5797 
   5798     if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
   5799         return (-1);
   5800 
   5801     incur = 0;
   5802     inblk = 0;
   5803     outcur = 0;
   5804     inmax = *inlen;
   5805     outmax = *tolen;
   5806     nbintmp = 0;
   5807 
   5808     while (1) {
   5809         if (incur >= inmax)
   5810             break;
   5811         cur = in[incur++];
   5812         is_ignore = 0;
   5813         if ((cur >= 'A') && (cur <= 'Z'))
   5814             cur = cur - 'A';
   5815         else if ((cur >= 'a') && (cur <= 'z'))
   5816             cur = cur - 'a' + 26;
   5817         else if ((cur >= '0') && (cur <= '9'))
   5818             cur = cur - '0' + 52;
   5819         else if (cur == '+')
   5820             cur = 62;
   5821         else if (cur == '/')
   5822             cur = 63;
   5823         else if (cur == '.')
   5824             cur = 0;
   5825         else if (cur == '=')    /*no op , end of the base64 stream */
   5826             is_end = 1;
   5827         else {
   5828             is_ignore = 1;
   5829             if (nbintmp == 0)
   5830                 inblk = incur;
   5831         }
   5832 
   5833         if (!is_ignore) {
   5834             int nbouttmp = 3;
   5835 
   5836             int is_break = 0;
   5837 
   5838             if (is_end) {
   5839                 if (nbintmp == 0)
   5840                     break;
   5841                 if ((nbintmp == 1) || (nbintmp == 2))
   5842                     nbouttmp = 1;
   5843                 else
   5844                     nbouttmp = 2;
   5845                 nbintmp = 3;
   5846                 is_break = 1;
   5847             }
   5848             intmp[nbintmp++] = cur;
   5849             /*
   5850              * if intmp is full, push the 4byte sequence as a 3 byte
   5851              * sequence out
   5852              */
   5853             if (nbintmp == 4) {
   5854                 nbintmp = 0;
   5855                 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
   5856                 outtmp[1] =
   5857                     ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
   5858                 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
   5859                 if (outcur + 3 >= outmax) {
   5860                     retval = 2;
   5861                     break;
   5862                 }
   5863 
   5864                 for (i = 0; i < nbouttmp; i++)
   5865                     to[outcur++] = outtmp[i];
   5866                 inblk = incur;
   5867             }
   5868 
   5869             if (is_break) {
   5870                 retval = 0;
   5871                 break;
   5872             }
   5873         }
   5874     }
   5875 
   5876     *tolen = outcur;
   5877     *inlen = inblk;
   5878     return (retval);
   5879 }
   5880 
   5881 /*
   5882  * Test routine for the xmlBase64Decode function
   5883  */
   5884 #if 0
   5885 int
   5886 main(int argc, char **argv)
   5887 {
   5888     char *input = "  VW4 gcGV0        \n      aXQgdGVzdCAuCg== ";
   5889 
   5890     char output[100];
   5891 
   5892     char output2[100];
   5893 
   5894     char output3[100];
   5895 
   5896     unsigned long inlen = strlen(input);
   5897 
   5898     unsigned long outlen = 100;
   5899 
   5900     int ret;
   5901 
   5902     unsigned long cons, tmp, tmp2, prod;
   5903 
   5904     /*
   5905      * Direct
   5906      */
   5907     ret = xmlBase64Decode(input, &inlen, output, &outlen);
   5908 
   5909     output[outlen] = 0;
   5910     printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
   5911            outlen, output)indent: Standard input:179: Error:Unmatched #endif
   5912 ;
   5913 
   5914     /*
   5915      * output chunking
   5916      */
   5917     cons = 0;
   5918     prod = 0;
   5919     while (cons < inlen) {
   5920         tmp = 5;
   5921         tmp2 = inlen - cons;
   5922 
   5923         printf("%ld %ld\n", cons, prod);
   5924         ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
   5925         cons += tmp2;
   5926         prod += tmp;
   5927         printf("%ld %ld\n", cons, prod);
   5928     }
   5929     output2[outlen] = 0;
   5930     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
   5931            prod, output2);
   5932 
   5933     /*
   5934      * input chunking
   5935      */
   5936     cons = 0;
   5937     prod = 0;
   5938     while (cons < inlen) {
   5939         tmp = 100 - prod;
   5940         tmp2 = inlen - cons;
   5941         if (tmp2 > 5)
   5942             tmp2 = 5;
   5943 
   5944         printf("%ld %ld\n", cons, prod);
   5945         ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
   5946         cons += tmp2;
   5947         prod += tmp;
   5948         printf("%ld %ld\n", cons, prod);
   5949     }
   5950     output3[outlen] = 0;
   5951     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
   5952            prod, output3);
   5953     return (0);
   5954 
   5955 }
   5956 #endif
   5957 #endif /* NOT_USED_YET */
   5958 #define bottom_xmlreader
   5959 #include "elfgcchack.h"
   5960 #endif /* LIBXML_READER_ENABLED */
   5961