Edit

kc3-lang/libxml2/xmlwriter.c

Branch :

  • Show log

    Commit

  • Author : Nick Wellnhofer
    Date : 2022-12-08 02:43:17
    Hash : dd3569ea
    Message : Remove XMLDECL macro from .c files

  • xmlwriter.c
  • /*
     * xmlwriter.c: XML text writer implementation
     *
     * For license and disclaimer see the license and disclaimer of
     * libxml2.
     *
     * alfred@mickautsch.de
     */
    
    #define IN_LIBXML
    #include "libxml.h"
    #include <string.h>
    
    #include <libxml/xmlmemory.h>
    #include <libxml/parser.h>
    #include <libxml/uri.h>
    #include <libxml/HTMLtree.h>
    
    #ifdef LIBXML_WRITER_ENABLED
    
    #include <libxml/xmlwriter.h>
    
    #include "private/buf.h"
    #include "private/enc.h"
    #include "private/error.h"
    #include "private/save.h"
    
    #define B64LINELEN 72
    #define B64CRLF "\r\n"
    
    /*
     * The following VA_COPY was coded following an example in
     * the Samba project.  It may not be sufficient for some
     * esoteric implementations of va_list but (hopefully) will
     * be sufficient for libxml2.
     */
    #ifndef VA_COPY
      #ifdef HAVE_VA_COPY
        #define VA_COPY(dest, src) va_copy(dest, src)
      #else
        #ifdef HAVE___VA_COPY
          #define VA_COPY(dest,src) __va_copy(dest, src)
        #else
          #ifndef VA_LIST_IS_ARRAY
            #define VA_COPY(dest,src) (dest) = (src)
          #else
            #include <string.h>
            #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
          #endif
        #endif
      #endif
    #endif
    
    /*
     * Types are kept private
     */
    typedef enum {
        XML_TEXTWRITER_NONE = 0,
        XML_TEXTWRITER_NAME,
        XML_TEXTWRITER_ATTRIBUTE,
        XML_TEXTWRITER_TEXT,
        XML_TEXTWRITER_PI,
        XML_TEXTWRITER_PI_TEXT,
        XML_TEXTWRITER_CDATA,
        XML_TEXTWRITER_DTD,
        XML_TEXTWRITER_DTD_TEXT,
        XML_TEXTWRITER_DTD_ELEM,
        XML_TEXTWRITER_DTD_ELEM_TEXT,
        XML_TEXTWRITER_DTD_ATTL,
        XML_TEXTWRITER_DTD_ATTL_TEXT,
        XML_TEXTWRITER_DTD_ENTY,    /* entity */
        XML_TEXTWRITER_DTD_ENTY_TEXT,
        XML_TEXTWRITER_DTD_PENT,    /* parameter entity */
        XML_TEXTWRITER_COMMENT
    } xmlTextWriterState;
    
    typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
    
    struct _xmlTextWriterStackEntry {
        xmlChar *name;
        xmlTextWriterState state;
    };
    
    typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
    struct _xmlTextWriterNsStackEntry {
        xmlChar *prefix;
        xmlChar *uri;
        xmlLinkPtr elem;
    };
    
    struct _xmlTextWriter {
        xmlOutputBufferPtr out;     /* output buffer */
        xmlListPtr nodes;           /* element name stack */
        xmlListPtr nsstack;         /* name spaces stack */
        int level;
        int indent;                 /* enable indent */
        int doindent;               /* internal indent flag */
        xmlChar *ichar;             /* indent character */
        char qchar;                 /* character used for quoting attribute values */
        xmlParserCtxtPtr ctxt;
        int no_doc_free;
        xmlDocPtr doc;
    };
    
    static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
    static int xmlCmpTextWriterStackEntry(const void *data0,
                                          const void *data1);
    static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
    static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
    static int xmlCmpTextWriterNsStackEntry(const void *data0,
                                            const void *data1);
    static int xmlTextWriterWriteDocCallback(void *context,
                                             const char *str, int len);
    static int xmlTextWriterCloseDocCallback(void *context);
    
    static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr) LIBXML_ATTR_FORMAT(1,0);
    static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
                                          const unsigned char *data);
    static void xmlTextWriterStartDocumentCallback(void *ctx);
    static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
    static int
      xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
                                           xmlTextWriterStackEntry * p);
    
    /**
     * xmlWriterErrMsg:
     * @ctxt:  a writer context
     * @error:  the error number
     * @msg:  the error message
     *
     * Handle a writer error
     */
    static void
    xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
                   const char *msg)
    {
        if (ctxt != NULL) {
    	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
    	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
    		    NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
        } else {
    	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
                        XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
        }
    }
    
    /**
     * xmlWriterErrMsgInt:
     * @ctxt:  a writer context
     * @error:  the error number
     * @msg:  the error message
     * @val:  an int
     *
     * Handle a writer error
     */
    static void LIBXML_ATTR_FORMAT(3,0)
    xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
                   const char *msg, int val)
    {
        if (ctxt != NULL) {
    	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
    	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
    		    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
        } else {
    	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
                        XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
        }
    }
    
    /**
     * xmlNewTextWriter:
     * @out:  an xmlOutputBufferPtr
     *
     * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
     * NOTE: the @out parameter will be deallocated when the writer is closed
     *       (if the call succeed.)
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriter(xmlOutputBufferPtr out)
    {
        xmlTextWriterPtr ret;
    
        ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
        if (ret == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriter : out of memory!\n");
            return NULL;
        }
        memset(ret, 0, sizeof(xmlTextWriter));
    
        ret->nodes = xmlListCreate(xmlFreeTextWriterStackEntry,
                                   xmlCmpTextWriterStackEntry);
        if (ret->nodes == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriter : out of memory!\n");
            xmlFree(ret);
            return NULL;
        }
    
        ret->nsstack = xmlListCreate(xmlFreeTextWriterNsStackEntry,
                                     xmlCmpTextWriterNsStackEntry);
        if (ret->nsstack == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriter : out of memory!\n");
            xmlListDelete(ret->nodes);
            xmlFree(ret);
            return NULL;
        }
    
        ret->out = out;
        ret->ichar = xmlStrdup(BAD_CAST " ");
        ret->qchar = '"';
    
        if (!ret->ichar) {
            xmlListDelete(ret->nodes);
            xmlListDelete(ret->nsstack);
            xmlFree(ret);
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriter : out of memory!\n");
            return NULL;
        }
    
        ret->doc = xmlNewDoc(NULL);
    
        ret->no_doc_free = 0;
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterFilename:
     * @uri:  the URI of the resource for the output
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @uri as output
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterFilename(const char *uri, int compression)
    {
        xmlTextWriterPtr ret;
        xmlOutputBufferPtr out;
    
        out = xmlOutputBufferCreateFilename(uri, NULL, compression);
        if (out == NULL) {
            xmlWriterErrMsg(NULL, XML_IO_EIO,
                            "xmlNewTextWriterFilename : cannot open uri\n");
            return NULL;
        }
    
        ret = xmlNewTextWriter(out);
        if (ret == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriterFilename : out of memory!\n");
            xmlOutputBufferClose(out);
            return NULL;
        }
    
        ret->indent = 0;
        ret->doindent = 0;
        return ret;
    }
    
    /**
     * xmlNewTextWriterMemory:
     * @buf:  xmlBufferPtr
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @buf as output
     * TODO: handle compression
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
    {
        xmlTextWriterPtr ret;
        xmlOutputBufferPtr out;
    
    /*::todo handle compression */
        out = xmlOutputBufferCreateBuffer(buf, NULL);
    
        if (out == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriterMemory : out of memory!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriter(out);
        if (ret == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlNewTextWriterMemory : out of memory!\n");
            xmlOutputBufferClose(out);
            return NULL;
        }
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterPushParser:
     * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @ctxt as output
     * NOTE: the @ctxt context will be freed with the resulting writer
     *       (if the call succeeds).
     * TODO: handle compression
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
                               int compression ATTRIBUTE_UNUSED)
    {
        xmlTextWriterPtr ret;
        xmlOutputBufferPtr out;
    
        if (ctxt == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterPushParser : invalid context!\n");
            return NULL;
        }
    
        out = xmlOutputBufferCreateIO(xmlTextWriterWriteDocCallback,
                                      xmlTextWriterCloseDocCallback,
                                      (void *) ctxt, NULL);
        if (out == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriter(out);
        if (ret == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
            xmlOutputBufferClose(out);
            return NULL;
        }
    
        ret->ctxt = ctxt;
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterDoc:
     * @doc: address of a xmlDocPtr to hold the new XML document tree
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @*doc as output
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
    {
        xmlTextWriterPtr ret;
        xmlSAXHandler saxHandler;
        xmlParserCtxtPtr ctxt;
    
        memset(&saxHandler, '\0', sizeof(saxHandler));
        xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
        saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
        saxHandler.startElement = xmlSAX2StartElement;
        saxHandler.endElement = xmlSAX2EndElement;
    
        ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
        if (ctxt == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                    "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
            return NULL;
        }
        /*
         * For some reason this seems to completely break if node names
         * are interned.
         */
        ctxt->dictNames = 0;
    
        ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
        if (ctxt->myDoc == NULL) {
            xmlFreeParserCtxt(ctxt);
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriterPushParser(ctxt, compression);
        if (ret == NULL) {
            xmlFreeDoc(ctxt->myDoc);
            xmlFreeParserCtxt(ctxt);
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                    "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
            return NULL;
        }
    
        xmlSetDocCompressMode(ctxt->myDoc, compression);
    
        if (doc != NULL) {
            *doc = ctxt->myDoc;
    	ret->no_doc_free = 1;
        }
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterTree:
     * @doc: xmlDocPtr
     * @node: xmlNodePtr or NULL for doc->children
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @doc as output
     * starting at @node
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
    {
        xmlTextWriterPtr ret;
        xmlSAXHandler saxHandler;
        xmlParserCtxtPtr ctxt;
    
        if (doc == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterTree : invalid document tree!\n");
            return NULL;
        }
    
        memset(&saxHandler, '\0', sizeof(saxHandler));
        xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
        saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
        saxHandler.startElement = xmlSAX2StartElement;
        saxHandler.endElement = xmlSAX2EndElement;
    
        ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
        if (ctxt == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
            return NULL;
        }
        /*
         * For some reason this seems to completely break if node names
         * are interned.
         */
        ctxt->dictNames = 0;
    
        ret = xmlNewTextWriterPushParser(ctxt, compression);
        if (ret == NULL) {
            xmlFreeParserCtxt(ctxt);
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
            return NULL;
        }
    
        ctxt->myDoc = doc;
        ctxt->node = node;
        ret->no_doc_free = 1;
    
        xmlSetDocCompressMode(doc, compression);
    
        return ret;
    }
    
    /**
     * xmlFreeTextWriter:
     * @writer:  the xmlTextWriterPtr
     *
     * Deallocate all the resources associated to the writer
     */
    void
    xmlFreeTextWriter(xmlTextWriterPtr writer)
    {
        if (writer == NULL)
            return;
    
        if (writer->out != NULL)
            xmlOutputBufferClose(writer->out);
    
        if (writer->nodes != NULL)
            xmlListDelete(writer->nodes);
    
        if (writer->nsstack != NULL)
            xmlListDelete(writer->nsstack);
    
        if (writer->ctxt != NULL) {
            if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
    	    xmlFreeDoc(writer->ctxt->myDoc);
    	    writer->ctxt->myDoc = NULL;
    	}
            xmlFreeParserCtxt(writer->ctxt);
        }
    
        if (writer->doc != NULL)
            xmlFreeDoc(writer->doc);
    
        if (writer->ichar != NULL)
            xmlFree(writer->ichar);
        xmlFree(writer);
    }
    
    /**
     * xmlTextWriterStartDocument:
     * @writer:  the xmlTextWriterPtr
     * @version:  the xml version ("1.0") or NULL for default ("1.0")
     * @encoding:  the encoding or NULL for default
     * @standalone: "yes" or "no" or NULL for default
     *
     * Start a new xml document
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
                               const char *encoding, const char *standalone)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlCharEncodingHandlerPtr encoder;
    
        if ((writer == NULL) || (writer->out == NULL)) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterStartDocument : invalid writer!\n");
            return -1;
        }
    
        lk = xmlListFront(writer->nodes);
        if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterStartDocument : not allowed in this context!\n");
            return -1;
        }
    
        encoder = NULL;
        if (encoding != NULL) {
            encoder = xmlFindCharEncodingHandler(encoding);
            if (encoder == NULL) {
                xmlWriterErrMsg(writer, XML_ERR_UNSUPPORTED_ENCODING,
                                "xmlTextWriterStartDocument : unsupported encoding\n");
                return -1;
            }
        }
    
        writer->out->encoder = encoder;
        if (encoder != NULL) {
    	if (writer->out->conv == NULL) {
    	    writer->out->conv = xmlBufCreateSize(4000);
    	}
            xmlCharEncOutput(writer->out, 1);
            if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
                writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
        } else
            writer->out->conv = NULL;
    
        sum = 0;
        count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
        if (count < 0)
            return -1;
        sum += count;
        if (version != 0)
            count = xmlOutputBufferWriteString(writer->out, version);
        else
            count = xmlOutputBufferWriteString(writer->out, "1.0");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
        if (count < 0)
            return -1;
        sum += count;
        if (writer->out->encoder != 0) {
            count = xmlOutputBufferWriteString(writer->out, " encoding=");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWriteString(writer->out,
                                           writer->out->encoder->name);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (standalone != 0) {
            count = xmlOutputBufferWriteString(writer->out, " standalone=");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWriteString(writer->out, standalone);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "?>\n");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDocument:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml document. All open elements are closed, and
     * the content is flushed to the output.
     *
     * Returns the bytes written or -1 in case of error
     */
    int
    xmlTextWriterEndDocument(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterEndDocument : invalid writer!\n");
            return -1;
        }
    
        sum = 0;
        while ((lk = xmlListFront(writer->nodes)) != NULL) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p == 0)
                break;
            switch (p->state) {
                case XML_TEXTWRITER_NAME:
                case XML_TEXTWRITER_ATTRIBUTE:
                case XML_TEXTWRITER_TEXT:
                    count = xmlTextWriterEndElement(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_PI:
                case XML_TEXTWRITER_PI_TEXT:
                    count = xmlTextWriterEndPI(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_CDATA:
                    count = xmlTextWriterEndCDATA(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_DTD:
                case XML_TEXTWRITER_DTD_TEXT:
                case XML_TEXTWRITER_DTD_ELEM:
                case XML_TEXTWRITER_DTD_ELEM_TEXT:
                case XML_TEXTWRITER_DTD_ATTL:
                case XML_TEXTWRITER_DTD_ATTL_TEXT:
                case XML_TEXTWRITER_DTD_ENTY:
                case XML_TEXTWRITER_DTD_ENTY_TEXT:
                case XML_TEXTWRITER_DTD_PENT:
                    count = xmlTextWriterEndDTD(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_COMMENT:
                    count = xmlTextWriterEndComment(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                default:
                    break;
            }
        }
    
        if (!writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        sum += xmlTextWriterFlush(writer);
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartComment:
     * @writer:  the xmlTextWriterPtr
     *
     * Start an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartComment(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterStartComment : invalid writer!\n");
            return -1;
        }
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_TEXT:
                    case XML_TEXTWRITER_NONE:
                        break;
                    case XML_TEXTWRITER_NAME:
                        /* Output namespace declarations */
                        count = xmlTextWriterOutputNSDecl(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        if (writer->indent) {
                            count =
                                xmlOutputBufferWriteString(writer->out, "\n");
                            if (count < 0)
                                return -1;
                            sum += count;
                        }
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
                    default:
                        return -1;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartElement : out of memory!\n");
            return -1;
        }
    
        p->name = NULL;
        p->state = XML_TEXTWRITER_COMMENT;
    
        xmlListPushFront(writer->nodes, p);
    
        if (writer->indent) {
            count = xmlTextWriterWriteIndent(writer);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<!--");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndComment:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndComment(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterEndComment : invalid writer!\n");
            return -1;
        }
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterEndComment : not allowed in this context!\n");
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_COMMENT:
                count = xmlOutputBufferWriteString(writer->out, "-->");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatComment:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
                                    const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatComment:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
                                     const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterWriteVFormatComment : invalid writer!\n");
            return -1;
        }
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteComment(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteComment:
     * @writer:  the xmlTextWriterPtr
     * @content:  comment string
     *
     * Write an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartComment(writer);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterEndComment(writer);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     *
     * Start an xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        return -1;
                    case XML_TEXTWRITER_NONE:
                        break;
    				case XML_TEXTWRITER_ATTRIBUTE:
    					count = xmlTextWriterEndAttribute(writer);
    					if (count < 0)
    						return -1;
    					sum += count;
    					/* fallthrough */
                    case XML_TEXTWRITER_NAME:
                        /* Output namespace declarations */
                        count = xmlTextWriterOutputNSDecl(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        if (writer->indent)
                            count =
                                xmlOutputBufferWriteString(writer->out, "\n");
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
                    default:
                        break;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartElement : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartElement : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_NAME;
    
        xmlListPushFront(writer->nodes, p);
    
        if (writer->indent) {
            count = xmlTextWriterWriteIndent(writer);
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<");
        if (count < 0)
            return -1;
        sum += count;
        count =
            xmlOutputBufferWriteString(writer->out, (const char *) p->name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix or NULL
     * @name:  element local name
     * @namespaceURI:  namespace URI or NULL
     *
     * Start an xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
                                const xmlChar * prefix, const xmlChar * name,
                                const xmlChar * namespaceURI)
    {
        int count;
        int sum;
        xmlChar *buf;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        buf = NULL;
        if (prefix != 0) {
            buf = xmlStrdup(prefix);
            buf = xmlStrcat(buf, BAD_CAST ":");
        }
        buf = xmlStrcat(buf, name);
    
        sum = 0;
        count = xmlTextWriterStartElement(writer, buf);
        xmlFree(buf);
        if (count < 0)
            return -1;
        sum += count;
    
        if (namespaceURI != 0) {
            xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
            if (p == 0) {
                xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                                "xmlTextWriterStartElementNS : out of memory!\n");
                return -1;
            }
    
            buf = xmlStrdup(BAD_CAST "xmlns");
            if (prefix != 0) {
                buf = xmlStrcat(buf, BAD_CAST ":");
                buf = xmlStrcat(buf, prefix);
            }
    
            p->prefix = buf;
            p->uri = xmlStrdup(namespaceURI);
            if (p->uri == 0) {
                xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                                "xmlTextWriterStartElementNS : out of memory!\n");
                xmlFree(p);
                return -1;
            }
            p->elem = xmlListFront(writer->nodes);
    
            xmlListPushFront(writer->nsstack, p);
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndElement:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndElement(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            xmlListDelete(writer->nsstack);
            writer->nsstack = NULL;
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0) {
            xmlListDelete(writer->nsstack);
            writer->nsstack = NULL;
            return -1;
        }
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                count = xmlTextWriterEndAttribute(writer);
                if (count < 0) {
                    xmlListDelete(writer->nsstack);
                    writer->nsstack = NULL;
                    return -1;
                }
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_NAME:
                /* Output namespace declarations */
                count = xmlTextWriterOutputNSDecl(writer);
                if (count < 0)
                    return -1;
                sum += count;
    
                if (writer->indent) /* next element needs indent */
                    writer->doindent = 1;
                count = xmlOutputBufferWriteString(writer->out, "/>");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            case XML_TEXTWRITER_TEXT:
                if ((writer->indent) && (writer->doindent)) {
                    count = xmlTextWriterWriteIndent(writer);
                    sum += count;
                    writer->doindent = 1;
                } else
                    writer->doindent = 1;
                count = xmlOutputBufferWriteString(writer->out, "</");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out,
                                                   (const char *) p->name);
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterFullEndElement:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml element. Writes an end tag even if the element is empty
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                count = xmlTextWriterEndAttribute(writer);
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_NAME:
                /* Output namespace declarations */
                count = xmlTextWriterOutputNSDecl(writer);
                if (count < 0)
                    return -1;
                sum += count;
    
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                if (writer->indent)
                    writer->doindent = 0;
                /* fallthrough */
            case XML_TEXTWRITER_TEXT:
                if ((writer->indent) && (writer->doindent)) {
                    count = xmlTextWriterWriteIndent(writer);
                    sum += count;
                    writer->doindent = 1;
                } else
                    writer->doindent = 1;
                count = xmlOutputBufferWriteString(writer->out, "</");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out,
                                                   (const char *) p->name);
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatRaw:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted raw xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
                                ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatRaw:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted raw xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
                                 va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteRaw(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteRawLen:
     * @writer:  the xmlTextWriterPtr
     * @content:  text string
     * @len:  length of the text string
     *
     * Write an xml text.
     * TODO: what about entities and special chars??
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
                             int len)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterWriteRawLen : invalid writer!\n");
            return -1;
        }
    
        if ((content == NULL) || (len < 0)) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterWriteRawLen : invalid content!\n");
            return -1;
        }
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            count = xmlTextWriterHandleStateDependencies(writer, p);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (writer->indent)
            writer->doindent = 0;
    
        if (content != NULL) {
            count =
                xmlOutputBufferWrite(writer->out, len, (const char *) content);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteRaw:
     * @writer:  the xmlTextWriterPtr
     * @content:  text string
     *
     * Write a raw xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
    {
        return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
    }
    
    /**
     * xmlTextWriterWriteFormatString:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
                                   ...)
    {
        int rc;
        va_list ap;
    
        if ((writer == NULL) || (format == NULL))
            return -1;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatString(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatString:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
                                    const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if ((writer == NULL) || (format == NULL))
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteString(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteString:
     * @writer:  the xmlTextWriterPtr
     * @content:  text string
     *
     * Write an xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
        xmlChar *buf;
    
        if ((writer == NULL) || (content == NULL))
            return -1;
    
        sum = 0;
        buf = (xmlChar *) content;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_NAME:
                    case XML_TEXTWRITER_TEXT:
    #if 0
                        buf = NULL;
    		    xmlOutputBufferWriteEscape(writer->out, content, NULL);
    #endif
                        buf = xmlEncodeSpecialChars(NULL, content);
                        break;
                    case XML_TEXTWRITER_ATTRIBUTE:
                        buf = NULL;
                        xmlBufAttrSerializeTxtContent(writer->out->buffer,
                                                      writer->doc, NULL, content);
                        break;
    		default:
    		    break;
                }
            }
        }
    
        if (buf != NULL) {
            count = xmlTextWriterWriteRaw(writer, buf);
    
            if (buf != content)     /* buf was allocated by us, so free it */
                xmlFree(buf);
    
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlOutputBufferWriteBase64:
     * @out: the xmlOutputBufferPtr
     * @data:   binary data
     * @len:  the number of bytes to encode
     *
     * Write base64 encoded data to an xmlOutputBuffer.
     * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    static int
    xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
                               const unsigned char *data)
    {
        static const unsigned char dtable[64] =
                {'A','B','C','D','E','F','G','H','I','J','K','L','M',
    	     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
    	     'a','b','c','d','e','f','g','h','i','j','k','l','m',
    	     'n','o','p','q','r','s','t','u','v','w','x','y','z',
    	     '0','1','2','3','4','5','6','7','8','9','+','/'};
    
        int i;
        int linelen;
        int count;
        int sum;
    
        if ((out == NULL) || (len < 0) || (data == NULL))
            return(-1);
    
        linelen = 0;
        sum = 0;
    
        i = 0;
        while (1) {
            unsigned char igroup[3];
            unsigned char ogroup[4];
            int c;
            int n;
    
            igroup[0] = igroup[1] = igroup[2] = 0;
            for (n = 0; n < 3 && i < len; n++, i++) {
                c = data[i];
                igroup[n] = (unsigned char) c;
            }
    
            if (n > 0) {
                ogroup[0] = dtable[igroup[0] >> 2];
                ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
                ogroup[2] =
                    dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
                ogroup[3] = dtable[igroup[2] & 0x3F];
    
                if (n < 3) {
                    ogroup[3] = '=';
                    if (n < 2) {
                        ogroup[2] = '=';
                    }
                }
    
                if (linelen >= B64LINELEN) {
                    count = xmlOutputBufferWrite(out, 2, B64CRLF);
                    if (count == -1)
                        return -1;
                    sum += count;
                    linelen = 0;
                }
                count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
                if (count == -1)
                    return -1;
                sum += count;
    
                linelen += 4;
            }
    
            if (i >= len)
                break;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteBase64:
     * @writer: the xmlTextWriterPtr
     * @data:   binary data
     * @start:  the position within the data of the first byte to encode
     * @len:  the number of bytes to encode
     *
     * Write an base64 encoded xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
                             int start, int len)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                count = xmlTextWriterHandleStateDependencies(writer, p);
                if (count < 0)
                    return -1;
                sum += count;
            }
        }
    
        if (writer->indent)
            writer->doindent = 0;
    
        count =
            xmlOutputBufferWriteBase64(writer->out, len,
                                       (unsigned char *) data + start);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlOutputBufferWriteBinHex:
     * @out: the xmlOutputBufferPtr
     * @data:   binary data
     * @len:  the number of bytes to encode
     *
     * Write hqx encoded data to an xmlOutputBuffer.
     * ::todo
     *
     * Returns the bytes written (may be 0 because of buffering)
     * or -1 in case of error
     */
    static int
    xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
                               int len, const unsigned char *data)
    {
        int count;
        int sum;
        static const char hex[16] =
    	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        int i;
    
        if ((out == NULL) || (data == NULL) || (len < 0)) {
            return -1;
        }
    
        sum = 0;
        for (i = 0; i < len; i++) {
            count =
                xmlOutputBufferWrite(out, 1,
                                     (const char *) &hex[data[i] >> 4]);
            if (count == -1)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWrite(out, 1,
                                     (const char *) &hex[data[i] & 0xF]);
            if (count == -1)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteBinHex:
     * @writer: the xmlTextWriterPtr
     * @data:   binary data
     * @start:  the position within the data of the first byte to encode
     * @len:  the number of bytes to encode
     *
     * Write a BinHex encoded xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
                             int start, int len)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                count = xmlTextWriterHandleStateDependencies(writer, p);
                if (count < 0)
                    return -1;
                sum += count;
            }
        }
    
        if (writer->indent)
            writer->doindent = 0;
    
        count =
            xmlOutputBufferWriteBinHex(writer->out, len,
                                       (unsigned char *) data + start);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     *
     * Start an xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                count = xmlTextWriterEndAttribute(writer);
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, " ");
                if (count < 0)
                    return -1;
                sum += count;
                count =
                    xmlOutputBufferWriteString(writer->out,
                                               (const char *) name);
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, "=");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_ATTRIBUTE;
                break;
            default:
                return -1;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix or NULL
     * @name:  element local name
     * @namespaceURI:  namespace URI or NULL
     *
     * Start an xml attribute with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
                                  const xmlChar * prefix, const xmlChar * name,
                                  const xmlChar * namespaceURI)
    {
        int count;
        int sum;
        xmlChar *buf;
        xmlTextWriterNsStackEntry *p;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        /* Handle namespace first in case of error */
        if (namespaceURI != 0) {
            xmlTextWriterNsStackEntry nsentry, *curns;
    
            buf = xmlStrdup(BAD_CAST "xmlns");
            if (prefix != 0) {
                buf = xmlStrcat(buf, BAD_CAST ":");
                buf = xmlStrcat(buf, prefix);
            }
    
            nsentry.prefix = buf;
            nsentry.uri = (xmlChar *)namespaceURI;
            nsentry.elem = xmlListFront(writer->nodes);
    
            curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
                                                               (void *)&nsentry);
            if ((curns != NULL)) {
                xmlFree(buf);
                if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
                    /* Namespace already defined on element skip */
                    buf = NULL;
                } else {
                    /* Prefix mismatch so error out */
                    return -1;
                }
            }
    
            /* Do not add namespace decl to list - it is already there */
            if (buf != NULL) {
                p = (xmlTextWriterNsStackEntry *)
                    xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
                if (p == 0) {
                    xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
    								        "xmlTextWriterStartAttributeNS : out of memory!\n");
                    return -1;
                }
    
                p->prefix = buf;
                p->uri = xmlStrdup(namespaceURI);
                if (p->uri == 0) {
                    xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartAttributeNS : out of memory!\n");
                    xmlFree(p);
                    return -1;
                }
                p->elem = xmlListFront(writer->nodes);
    
                xmlListPushFront(writer->nsstack, p);
            }
        }
    
        buf = NULL;
        if (prefix != 0) {
            buf = xmlStrdup(prefix);
            buf = xmlStrcat(buf, BAD_CAST ":");
        }
        buf = xmlStrcat(buf, name);
    
        sum = 0;
        count = xmlTextWriterStartAttribute(writer, buf);
        xmlFree(buf);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndAttribute:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0) {
            return -1;
        }
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                p->state = XML_TEXTWRITER_NAME;
    
                count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
                if (count < 0) {
                    return -1;
                }
                sum += count;
                break;
            default:
                return -1;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  attribute name
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
                                      const xmlChar * name, const char *format,
                                      ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  attribute name
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteAttribute(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  attribute name
     * @content:  attribute content
     *
     * Write an xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
                                const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartAttribute(writer, name);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterEndAttribute(writer);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  attribute local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml attribute.with namespace support
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
                                        const xmlChar * prefix,
                                        const xmlChar * name,
                                        const xmlChar * namespaceURI,
                                        const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
                                                  namespaceURI, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  attribute local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml attribute.with namespace support
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
                                         const xmlChar * prefix,
                                         const xmlChar * name,
                                         const xmlChar * namespaceURI,
                                         const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
                                           buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  attribute local name
     * @namespaceURI:  namespace URI
     * @content:  attribute content
     *
     * Write an xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
                                  const xmlChar * prefix, const xmlChar * name,
                                  const xmlChar * namespaceURI,
                                  const xmlChar * content)
    {
        int count;
        int sum;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterEndAttribute(writer);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
                                    const xmlChar * name, const char *format,
                                    ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
                                     const xmlChar * name, const char *format,
                                     va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteElement(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     * @content:  element content
     *
     * Write an xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
                              const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartElement(writer, name);
        if (count == -1)
            return -1;
        sum += count;
        if (content != NULL) {
    	count = xmlTextWriterWriteString(writer, content);
    	if (count == -1)
    	    return -1;
    	sum += count;
        }
        count = xmlTextWriterEndElement(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  element local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
                                      const xmlChar * prefix,
                                      const xmlChar * name,
                                      const xmlChar * namespaceURI,
                                      const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
                                                namespaceURI, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  element local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
                                       const xmlChar * prefix,
                                       const xmlChar * name,
                                       const xmlChar * namespaceURI,
                                       const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
                                         buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  element local name
     * @namespaceURI:  namespace URI
     * @content:  element content
     *
     * Write an xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
                                const xmlChar * prefix, const xmlChar * name,
                                const xmlChar * namespaceURI,
                                const xmlChar * content)
    {
        int count;
        int sum;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        count =
            xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
        count = xmlTextWriterEndElement(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartPI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     *
     * Start an xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (target == NULL) || (*target == '\0'))
            return -1;
    
        if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
            return -1;
        }
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_ATTRIBUTE:
                        count = xmlTextWriterEndAttribute(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        /* fallthrough */
                    case XML_TEXTWRITER_NAME:
                        /* Output namespace declarations */
                        count = xmlTextWriterOutputNSDecl(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
                    case XML_TEXTWRITER_NONE:
                    case XML_TEXTWRITER_TEXT:
                    case XML_TEXTWRITER_DTD:
                        break;
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                                        "xmlTextWriterStartPI : nested PI!\n");
                        return -1;
                    default:
                        return -1;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartPI : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(target);
        if (p->name == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartPI : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_PI;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<?");
        if (count < 0)
            return -1;
        sum += count;
        count =
            xmlOutputBufferWriteString(writer->out, (const char *) p->name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndPI:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndPI(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return 0;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return 0;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_PI:
            case XML_TEXTWRITER_PI_TEXT:
                count = xmlOutputBufferWriteString(writer->out, "?>");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
    	if (count < 0)
    	return -1;
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatPI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
                               const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatPI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
                                const xmlChar * target, const char *format,
                                va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWritePI(writer, target, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWritePI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     * @content:  PI content
     *
     * Write an xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
                         const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartPI(writer, target);
        if (count == -1)
            return -1;
        sum += count;
        if (content != 0) {
            count = xmlTextWriterWriteString(writer, content);
            if (count == -1)
                return -1;
            sum += count;
        }
        count = xmlTextWriterEndPI(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartCDATA:
     * @writer:  the xmlTextWriterPtr
     *
     * Start an xml CDATA section.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_NONE:
    		case XML_TEXTWRITER_TEXT:
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        break;
                    case XML_TEXTWRITER_ATTRIBUTE:
                        count = xmlTextWriterEndAttribute(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        /* fallthrough */
                    case XML_TEXTWRITER_NAME:
                        /* Output namespace declarations */
                        count = xmlTextWriterOutputNSDecl(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
                    case XML_TEXTWRITER_CDATA:
                        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                                        "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
                        return -1;
                    default:
                        return -1;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartCDATA : out of memory!\n");
            return -1;
        }
    
        p->name = NULL;
        p->state = XML_TEXTWRITER_CDATA;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndCDATA:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml CDATA section.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_CDATA:
                count = xmlOutputBufferWriteString(writer->out, "]]>");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatCDATA:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml CDATA.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
                                  ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatCDATA:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml CDATA.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
                                   va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteCDATA(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteCDATA:
     * @writer:  the xmlTextWriterPtr
     * @content:  CDATA content
     *
     * Write an xml CDATA.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartCDATA(writer);
        if (count == -1)
            return -1;
        sum += count;
        if (content != 0) {
            count = xmlTextWriterWriteString(writer, content);
            if (count == -1)
                return -1;
            sum += count;
        }
        count = xmlTextWriterEndCDATA(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     *
     * Start an xml DTD.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTD(xmlTextWriterPtr writer,
                          const xmlChar * name,
                          const xmlChar * pubid, const xmlChar * sysid)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTD : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTD : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        if (pubid != 0) {
            if (sysid == 0) {
                xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                                "xmlTextWriterStartDTD : system identifier needed!\n");
                return -1;
            }
    
            if (writer->indent)
                count = xmlOutputBufferWrite(writer->out, 1, "\n");
            else
                count = xmlOutputBufferWrite(writer->out, 1, " ");
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) pubid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (sysid != 0) {
            if (pubid == 0) {
                if (writer->indent)
                    count = xmlOutputBufferWrite(writer->out, 1, "\n");
                else
                    count = xmlOutputBufferWrite(writer->out, 1, " ");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
                if (count < 0)
                    return -1;
                sum += count;
            } else {
    			if (writer->indent)
                count = xmlOutputBufferWriteString(writer->out, "\n       ");
                else
                    count = xmlOutputBufferWrite(writer->out, 1, " ");
                if (count < 0)
                    return -1;
                sum += count;
            }
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) sysid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDTD:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml DTD.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndDTD(xmlTextWriterPtr writer)
    {
        int loop;
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        loop = 1;
        while (loop) {
            lk = xmlListFront(writer->nodes);
            if (lk == NULL)
                break;
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p == 0)
                break;
            switch (p->state) {
                case XML_TEXTWRITER_DTD_TEXT:
                    count = xmlOutputBufferWriteString(writer->out, "]");
                    if (count < 0)
                        return -1;
                    sum += count;
                    /* fallthrough */
                case XML_TEXTWRITER_DTD:
                    count = xmlOutputBufferWriteString(writer->out, ">");
    
                    if (writer->indent) {
                        if (count < 0)
                            return -1;
                        sum += count;
                        count = xmlOutputBufferWriteString(writer->out, "\n");
                    }
    
                    xmlListPopFront(writer->nodes);
                    break;
                case XML_TEXTWRITER_DTD_ELEM:
                case XML_TEXTWRITER_DTD_ELEM_TEXT:
                    count = xmlTextWriterEndDTDElement(writer);
                    break;
                case XML_TEXTWRITER_DTD_ATTL:
                case XML_TEXTWRITER_DTD_ATTL_TEXT:
                    count = xmlTextWriterEndDTDAttlist(writer);
                    break;
                case XML_TEXTWRITER_DTD_ENTY:
                case XML_TEXTWRITER_DTD_PENT:
                case XML_TEXTWRITER_DTD_ENTY_TEXT:
                    count = xmlTextWriterEndDTDEntity(writer);
                    break;
                case XML_TEXTWRITER_COMMENT:
                    count = xmlTextWriterEndComment(writer);
                    break;
                default:
                    loop = 0;
                    continue;
            }
    
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a DTD with a formatted markup declarations part.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
                                const xmlChar * name,
                                const xmlChar * pubid,
                                const xmlChar * sysid, const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
                                          ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a DTD with a formatted markup declarations part.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
                                 const xmlChar * name,
                                 const xmlChar * pubid,
                                 const xmlChar * sysid,
                                 const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @subset:  string content of the DTD
     *
     * Write a DTD.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
                          const xmlChar * name,
                          const xmlChar * pubid,
                          const xmlChar * sysid, const xmlChar * subset)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
        if (count == -1)
            return -1;
        sum += count;
        if (subset != 0) {
            count = xmlTextWriterWriteString(writer, subset);
            if (count == -1)
                return -1;
            sum += count;
        }
        count = xmlTextWriterEndDTD(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     *
     * Start an xml DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p != 0) {
            switch (p->state) {
                case XML_TEXTWRITER_DTD:
                    count = xmlOutputBufferWriteString(writer->out, " [");
                    if (count < 0)
                        return -1;
                    sum += count;
                    if (writer->indent) {
                        count = xmlOutputBufferWriteString(writer->out, "\n");
                        if (count < 0)
                            return -1;
                        sum += count;
                    }
                    p->state = XML_TEXTWRITER_DTD_TEXT;
                    /* fallthrough */
                case XML_TEXTWRITER_DTD_TEXT:
                case XML_TEXTWRITER_NONE:
                    break;
                default:
                    return -1;
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD_ELEM;
    
        xmlListPushFront(writer->nodes, p);
    
        if (writer->indent) {
            count = xmlTextWriterWriteIndent(writer);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDTDElement:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD_ELEM:
            case XML_TEXTWRITER_DTD_ELEM_TEXT:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
                                        const xmlChar * name,
                                        const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteDTDElement(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     * @content:  content of the element
     *
     * Write a DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
                                 const xmlChar * name, const xmlChar * content)
    {
        int count;
        int sum;
    
        if (content == NULL)
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDElement(writer, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDElement(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     *
     * Start an xml DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p != 0) {
            switch (p->state) {
                case XML_TEXTWRITER_DTD:
                    count = xmlOutputBufferWriteString(writer->out, " [");
                    if (count < 0)
                        return -1;
                    sum += count;
                    if (writer->indent) {
                        count = xmlOutputBufferWriteString(writer->out, "\n");
                        if (count < 0)
                            return -1;
                        sum += count;
                    }
                    p->state = XML_TEXTWRITER_DTD_TEXT;
                    /* fallthrough */
                case XML_TEXTWRITER_DTD_TEXT:
                case XML_TEXTWRITER_NONE:
                    break;
                default:
                    return -1;
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTDAttlist : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTDAttlist : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD_ATTL;
    
        xmlListPushFront(writer->nodes, p);
    
        if (writer->indent) {
            count = xmlTextWriterWriteIndent(writer);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml DTD attribute list.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD_ATTL:
            case XML_TEXTWRITER_DTD_ATTL_TEXT:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
                                        const xmlChar * name,
                                        const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     * @content:  content of the ATTLIST
     *
     * Write a DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
                                 const xmlChar * name, const xmlChar * content)
    {
        int count;
        int sum;
    
        if (content == NULL)
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDAttlist(writer, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDAttlist(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTDEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD ATTLIST
     *
     * Start an xml DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
                                int pe, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
    
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_DTD:
                        count = xmlOutputBufferWriteString(writer->out, " [");
                        if (count < 0)
                            return -1;
                        sum += count;
                        if (writer->indent) {
                            count =
                                xmlOutputBufferWriteString(writer->out, "\n");
                            if (count < 0)
                                return -1;
                            sum += count;
                        }
                        p->state = XML_TEXTWRITER_DTD_TEXT;
                        /* fallthrough */
                    case XML_TEXTWRITER_DTD_TEXT:
                    case XML_TEXTWRITER_NONE:
                        break;
                    default:
                        return -1;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            xmlFree(p);
            return -1;
        }
    
        if (pe != 0)
            p->state = XML_TEXTWRITER_DTD_PENT;
        else
            p->state = XML_TEXTWRITER_DTD_ENTY;
    
        xmlListPushFront(writer->nodes, p);
    
        if (writer->indent) {
            count = xmlTextWriterWriteIndent(writer);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
        if (count < 0)
            return -1;
        sum += count;
    
        if (pe != 0) {
            count = xmlOutputBufferWriteString(writer->out, "% ");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDTDEntity:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml DTD entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD_ENTY_TEXT:
                count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
                if (count < 0)
                    return -1;
                sum += count;
                /* Falls through. */
            case XML_TEXTWRITER_DTD_ENTY:
            case XML_TEXTWRITER_DTD_PENT:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
            count = xmlOutputBufferWriteString(writer->out, "\n");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTDInternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                              int pe,
                                              const xmlChar * name,
                                              const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
                                                        format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTDInternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                               int pe,
                                               const xmlChar * name,
                                               const char *format,
                                               va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == NULL)
            return -1;
    
        rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTDEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @ndataid:  the xml notation name.
     * @content:  content of the entity
     *
     * Write a DTD entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
                                int pe,
                                const xmlChar * name,
                                const xmlChar * pubid,
                                const xmlChar * sysid,
                                const xmlChar * ndataid,
                                const xmlChar * content)
    {
        if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
            return -1;
        if ((pe != 0) && (ndataid != NULL))
            return -1;
    
        if ((pubid == NULL) && (sysid == NULL))
            return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
                                                       content);
    
        return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
                                                   sysid, ndataid);
    }
    
    /**
     * xmlTextWriterWriteDTDInternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @content:  content of the entity
     *
     * Write a DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
                                        int pe,
                                        const xmlChar * name,
                                        const xmlChar * content)
    {
        int count;
        int sum;
    
        if ((name == NULL) || (*name == '\0') || (content == NULL))
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDEntity(writer, pe, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDEntity(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteDTDExternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @ndataid:  the xml notation name.
     *
     * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
                                        int pe,
                                        const xmlChar * name,
                                        const xmlChar * pubid,
                                        const xmlChar * sysid,
                                        const xmlChar * ndataid)
    {
        int count;
        int sum;
    
        if (((pubid == NULL) && (sysid == NULL)))
            return -1;
        if ((pe != 0) && (ndataid != NULL))
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDEntity(writer, pe, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count =
            xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
                                                        ndataid);
        if (count < 0)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDEntity(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteDTDExternalEntityContents:
     * @writer:  the xmlTextWriterPtr
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @ndataid:  the xml notation name.
     *
     * Write the contents of a DTD external entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
                                                const xmlChar * pubid,
                                                const xmlChar * sysid,
                                                const xmlChar * ndataid)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
            return -1;
        }
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD_ENTY:
                break;
            case XML_TEXTWRITER_DTD_PENT:
                if (ndataid != NULL) {
                    xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                                    "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
                    return -1;
                }
                break;
            default:
                xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                                "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
                return -1;
        }
    
        if (pubid != 0) {
            if (sysid == 0) {
                xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
                                "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
                return -1;
            }
    
            count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) pubid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (sysid != 0) {
            if (pubid == 0) {
                count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
                if (count < 0)
                    return -1;
                sum += count;
            }
    
            count = xmlOutputBufferWriteString(writer->out, " ");
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) sysid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (ndataid != NULL) {
            count = xmlOutputBufferWriteString(writer->out, " NDATA ");
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out,
                                           (const char *) ndataid);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteDTDNotation:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the xml notation
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     *
     * Write a DTD entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
                                  const xmlChar * name,
                                  const xmlChar * pubid, const xmlChar * sysid)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p != 0) {
            switch (p->state) {
                case XML_TEXTWRITER_DTD:
                    count = xmlOutputBufferWriteString(writer->out, " [");
                    if (count < 0)
                        return -1;
                    sum += count;
                    if (writer->indent) {
                        count = xmlOutputBufferWriteString(writer->out, "\n");
                        if (count < 0)
                            return -1;
                        sum += count;
                    }
                    p->state = XML_TEXTWRITER_DTD_TEXT;
                    /* fallthrough */
                case XML_TEXTWRITER_DTD_TEXT:
                    break;
                default:
                    return -1;
            }
        }
    
        if (writer->indent) {
            count = xmlTextWriterWriteIndent(writer);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        if (pubid != 0) {
            count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) pubid);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (sysid != 0) {
            if (pubid == 0) {
                count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
                if (count < 0)
                    return -1;
                sum += count;
            }
            count = xmlOutputBufferWriteString(writer->out, " ");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) sysid);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, ">");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterFlush:
     * @writer:  the xmlTextWriterPtr
     *
     * Flush the output buffer.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterFlush(xmlTextWriterPtr writer)
    {
        int count;
    
        if (writer == NULL)
            return -1;
    
        if (writer->out == NULL)
            count = 0;
        else
            count = xmlOutputBufferFlush(writer->out);
    
        return count;
    }
    
    /**
     * misc
     */
    
    /**
     * xmlFreeTextWriterStackEntry:
     * @lk:  the xmlLinkPtr
     *
     * Free callback for the xmlList.
     */
    static void
    xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
    {
        xmlTextWriterStackEntry *p;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return;
    
        if (p->name != 0)
            xmlFree(p->name);
        xmlFree(p);
    }
    
    /**
     * xmlCmpTextWriterStackEntry:
     * @data0:  the first data
     * @data1:  the second data
     *
     * Compare callback for the xmlList.
     *
     * Returns -1, 0, 1
     */
    static int
    xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
    {
        xmlTextWriterStackEntry *p0;
        xmlTextWriterStackEntry *p1;
    
        if (data0 == data1)
            return 0;
    
        if (data0 == 0)
            return -1;
    
        if (data1 == 0)
            return 1;
    
        p0 = (xmlTextWriterStackEntry *) data0;
        p1 = (xmlTextWriterStackEntry *) data1;
    
        return xmlStrcmp(p0->name, p1->name);
    }
    
    /**
     * misc
     */
    
    /**
     * xmlTextWriterOutputNSDecl:
     * @writer:  the xmlTextWriterPtr
     *
     * Output the current namespace declarations.
     */
    static int
    xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
    {
        xmlLinkPtr lk;
        xmlTextWriterNsStackEntry *np;
        int count;
        int sum;
    
        sum = 0;
        while (!xmlListEmpty(writer->nsstack)) {
            xmlChar *namespaceURI = NULL;
            xmlChar *prefix = NULL;
    
            lk = xmlListFront(writer->nsstack);
            np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
    
            if (np != 0) {
                namespaceURI = xmlStrdup(np->uri);
                prefix = xmlStrdup(np->prefix);
            }
    
            xmlListPopFront(writer->nsstack);
    
            if (np != 0) {
                count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
                xmlFree(namespaceURI);
                xmlFree(prefix);
    
                if (count < 0) {
                    xmlListDelete(writer->nsstack);
                    writer->nsstack = NULL;
                    return -1;
                }
                sum += count;
            }
        }
        return sum;
    }
    
    /**
     * xmlFreeTextWriterNsStackEntry:
     * @lk:  the xmlLinkPtr
     *
     * Free callback for the xmlList.
     */
    static void
    xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
    {
        xmlTextWriterNsStackEntry *p;
    
        p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return;
    
        if (p->prefix != 0)
            xmlFree(p->prefix);
        if (p->uri != 0)
            xmlFree(p->uri);
    
        xmlFree(p);
    }
    
    /**
     * xmlCmpTextWriterNsStackEntry:
     * @data0:  the first data
     * @data1:  the second data
     *
     * Compare callback for the xmlList.
     *
     * Returns -1, 0, 1
     */
    static int
    xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
    {
        xmlTextWriterNsStackEntry *p0;
        xmlTextWriterNsStackEntry *p1;
        int rc;
    
        if (data0 == data1)
            return 0;
    
        if (data0 == 0)
            return -1;
    
        if (data1 == 0)
            return 1;
    
        p0 = (xmlTextWriterNsStackEntry *) data0;
        p1 = (xmlTextWriterNsStackEntry *) data1;
    
        rc = xmlStrcmp(p0->prefix, p1->prefix);
    
        if ((rc != 0) || (p0->elem != p1->elem))
            rc = -1;
    
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDocCallback:
     * @context:  the xmlBufferPtr
     * @str:  the data to write
     * @len:  the length of the data
     *
     * Write callback for the xmlOutputBuffer with target xmlBuffer
     *
     * Returns -1, 0, 1
     */
    static int
    xmlTextWriterWriteDocCallback(void *context, const char *str, int len)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
        int rc;
    
        if ((rc = xmlParseChunk(ctxt, str, len, 0)) != 0) {
            xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterWriteDocCallback : XML error %d !\n",
                            rc);
            return -1;
        }
    
        return len;
    }
    
    /**
     * xmlTextWriterCloseDocCallback:
     * @context:  the xmlBufferPtr
     *
     * Close callback for the xmlOutputBuffer with target xmlBuffer
     *
     * Returns -1, 0, 1
     */
    static int
    xmlTextWriterCloseDocCallback(void *context)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
        int rc;
    
        if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
            xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
                            "xmlTextWriterCloseDocCallback : XML error %d !\n",
                            rc);
            return -1;
        }
    
        return 0;
    }
    
    /**
     * xmlTextWriterVSprintf:
     * @format:  see printf
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Utility function for formatted output
     *
     * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
     */
    static xmlChar *
    xmlTextWriterVSprintf(const char *format, va_list argptr)
    {
        int size;
        int count;
        xmlChar *buf;
        va_list locarg;
    
        size = BUFSIZ;
        buf = (xmlChar *) xmlMalloc(size);
        if (buf == NULL) {
            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                            "xmlTextWriterVSprintf : out of memory!\n");
            return NULL;
        }
    
        VA_COPY(locarg, argptr);
        while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
               || (count == size - 1) || (count == size) || (count > size)) {
    	va_end(locarg);
            xmlFree(buf);
            size += BUFSIZ;
            buf = (xmlChar *) xmlMalloc(size);
            if (buf == NULL) {
                xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
                                "xmlTextWriterVSprintf : out of memory!\n");
                return NULL;
            }
    	VA_COPY(locarg, argptr);
        }
        va_end(locarg);
    
        return buf;
    }
    
    /**
     * xmlTextWriterStartDocumentCallback:
     * @ctx: the user data (XML parser context)
     *
     * called at the start of document processing.
     */
    static void
    xmlTextWriterStartDocumentCallback(void *ctx)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        xmlDocPtr doc;
    
        if (ctxt->html) {
    #ifdef LIBXML_HTML_ENABLED
            if (ctxt->myDoc == NULL)
                ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
            if (ctxt->myDoc == NULL) {
                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    ctxt->sax->error(ctxt->userData,
                                     "SAX.startDocument(): out of memory\n");
                ctxt->errNo = XML_ERR_NO_MEMORY;
                ctxt->instate = XML_PARSER_EOF;
                ctxt->disableSAX = 1;
                return;
            }
    #else
            xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
                            "libxml2 built without HTML support\n");
            ctxt->errNo = XML_ERR_INTERNAL_ERROR;
            ctxt->instate = XML_PARSER_EOF;
            ctxt->disableSAX = 1;
            return;
    #endif
        } else {
            doc = ctxt->myDoc;
            if (doc == NULL)
                doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
            if (doc != NULL) {
                if (doc->children == NULL) {
                    if (ctxt->encoding != NULL)
                        doc->encoding = xmlStrdup(ctxt->encoding);
                    else
                        doc->encoding = NULL;
                    doc->standalone = ctxt->standalone;
                }
            } else {
                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    ctxt->sax->error(ctxt->userData,
                                     "SAX.startDocument(): out of memory\n");
                ctxt->errNo = XML_ERR_NO_MEMORY;
                ctxt->instate = XML_PARSER_EOF;
                ctxt->disableSAX = 1;
                return;
            }
        }
        if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
            (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
            ctxt->myDoc->URL =
                xmlCanonicPath((const xmlChar *) ctxt->input->filename);
            if (ctxt->myDoc->URL == NULL)
                ctxt->myDoc->URL =
                    xmlStrdup((const xmlChar *) ctxt->input->filename);
        }
    }
    
    /**
     * xmlTextWriterSetIndent:
     * @writer:  the xmlTextWriterPtr
     * @indent:  do indentation?
     *
     * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
     *
     * Returns -1 on error or 0 otherwise.
     */
    int
    xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
    {
        if ((writer == NULL) || (indent < 0))
            return -1;
    
        writer->indent = indent;
        writer->doindent = 1;
    
        return 0;
    }
    
    /**
     * xmlTextWriterSetIndentString:
     * @writer:  the xmlTextWriterPtr
     * @str:  the xmlChar string
     *
     * Set string indentation.
     *
     * Returns -1 on error or 0 otherwise.
     */
    int
    xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
    {
        if ((writer == NULL) || (!str))
            return -1;
    
        if (writer->ichar != NULL)
            xmlFree(writer->ichar);
        writer->ichar = xmlStrdup(str);
    
        if (!writer->ichar)
            return -1;
        else
            return 0;
    }
    
    /**
     * xmlTextWriterSetQuoteChar:
     * @writer:  the xmlTextWriterPtr
     * @quotechar:  the quote character
     *
     * Set the character used for quoting attributes.
     *
     * Returns -1 on error or 0 otherwise.
     */
    int
    xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
    {
        if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
            return -1;
    
        writer->qchar = quotechar;
    
        return 0;
    }
    
    /**
     * xmlTextWriterWriteIndent:
     * @writer:  the xmlTextWriterPtr
     *
     * Write indent string.
     *
     * Returns -1 on error or the number of strings written.
     */
    static int
    xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
    {
        int lksize;
        int i;
        int ret;
    
        lksize = xmlListSize(writer->nodes);
        if (lksize < 1)
            return (-1);            /* list is empty */
        for (i = 0; i < (lksize - 1); i++) {
            ret = xmlOutputBufferWriteString(writer->out,
                                             (const char *) writer->ichar);
            if (ret == -1)
                return (-1);
        }
    
        return (lksize - 1);
    }
    
    /**
     * xmlTextWriterHandleStateDependencies:
     * @writer:  the xmlTextWriterPtr
     * @p:  the xmlTextWriterStackEntry
     *
     * Write state dependent strings.
     *
     * Returns -1 on error or the number of characters written.
     */
    static int
    xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
                                         xmlTextWriterStackEntry * p)
    {
        int count;
        int sum;
        char extra[3];
    
        if (writer == NULL)
            return -1;
    
        if (p == NULL)
            return 0;
    
        sum = 0;
        extra[0] = extra[1] = extra[2] = '\0';
        if (p != 0) {
            sum = 0;
            switch (p->state) {
                case XML_TEXTWRITER_NAME:
                    /* Output namespace declarations */
                    count = xmlTextWriterOutputNSDecl(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    extra[0] = '>';
                    p->state = XML_TEXTWRITER_TEXT;
                    break;
                case XML_TEXTWRITER_PI:
                    extra[0] = ' ';
                    p->state = XML_TEXTWRITER_PI_TEXT;
                    break;
                case XML_TEXTWRITER_DTD:
                    extra[0] = ' ';
                    extra[1] = '[';
                    p->state = XML_TEXTWRITER_DTD_TEXT;
                    break;
                case XML_TEXTWRITER_DTD_ELEM:
                    extra[0] = ' ';
                    p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
                    break;
                case XML_TEXTWRITER_DTD_ATTL:
                    extra[0] = ' ';
                    p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
                    break;
                case XML_TEXTWRITER_DTD_ENTY:
                case XML_TEXTWRITER_DTD_PENT:
                    extra[0] = ' ';
                    extra[1] = writer->qchar;
                    p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
                    break;
                default:
                    break;
            }
        }
    
        if (*extra != '\0') {
            count = xmlOutputBufferWriteString(writer->out, extra);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    #endif