File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / xmlreader.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:37:58 2012 UTC (12 years, 5 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>