Home | History | Annotate | Download | only in libxml2
      1 
      2 /*
      3  * xmlwriter.c: XML text writer implementation
      4  *
      5  * For license and disclaimer see the license and disclaimer of
      6  * libxml2.
      7  *
      8  * alfred (at) mickautsch.de
      9  */
     10 
     11 #define IN_LIBXML
     12 #include "libxml.h"
     13 #include <string.h>
     14 
     15 #include <libxml/xmlmemory.h>
     16 #include <libxml/parser.h>
     17 #include <libxml/uri.h>
     18 #include <libxml/HTMLtree.h>
     19 
     20 #ifdef LIBXML_WRITER_ENABLED
     21 
     22 #include <libxml/xmlwriter.h>
     23 
     24 #include "buf.h"
     25 #include "enc.h"
     26 #include "save.h"
     27 
     28 #define B64LINELEN 72
     29 #define B64CRLF "\r\n"
     30 
     31 /*
     32  * The following VA_COPY was coded following an example in
     33  * the Samba project.  It may not be sufficient for some
     34  * esoteric implementations of va_list (i.e. it may need
     35  * something involving a memcpy) but (hopefully) will be
     36  * sufficient for libxml2.
     37  */
     38 #ifndef VA_COPY
     39   #ifdef HAVE_VA_COPY
     40     #define VA_COPY(dest, src) va_copy(dest, src)
     41   #else
     42     #ifdef HAVE___VA_COPY
     43       #define VA_COPY(dest,src) __va_copy(dest, src)
     44     #else
     45       #define VA_COPY(dest,src) (dest) = (src)
     46     #endif
     47   #endif
     48 #endif
     49 
     50 /*
     51  * Types are kept private
     52  */
     53 typedef enum {
     54     XML_TEXTWRITER_NONE = 0,
     55     XML_TEXTWRITER_NAME,
     56     XML_TEXTWRITER_ATTRIBUTE,
     57     XML_TEXTWRITER_TEXT,
     58     XML_TEXTWRITER_PI,
     59     XML_TEXTWRITER_PI_TEXT,
     60     XML_TEXTWRITER_CDATA,
     61     XML_TEXTWRITER_DTD,
     62     XML_TEXTWRITER_DTD_TEXT,
     63     XML_TEXTWRITER_DTD_ELEM,
     64     XML_TEXTWRITER_DTD_ELEM_TEXT,
     65     XML_TEXTWRITER_DTD_ATTL,
     66     XML_TEXTWRITER_DTD_ATTL_TEXT,
     67     XML_TEXTWRITER_DTD_ENTY,    /* entity */
     68     XML_TEXTWRITER_DTD_ENTY_TEXT,
     69     XML_TEXTWRITER_DTD_PENT,    /* parameter entity */
     70     XML_TEXTWRITER_COMMENT
     71 } xmlTextWriterState;
     72 
     73 typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
     74 
     75 struct _xmlTextWriterStackEntry {
     76     xmlChar *name;
     77     xmlTextWriterState state;
     78 };
     79 
     80 typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
     81 struct _xmlTextWriterNsStackEntry {
     82     xmlChar *prefix;
     83     xmlChar *uri;
     84     xmlLinkPtr elem;
     85 };
     86 
     87 struct _xmlTextWriter {
     88     xmlOutputBufferPtr out;     /* output buffer */
     89     xmlListPtr nodes;           /* element name stack */
     90     xmlListPtr nsstack;         /* name spaces stack */
     91     int level;
     92     int indent;                 /* enable indent */
     93     int doindent;               /* internal indent flag */
     94     xmlChar *ichar;             /* indent character */
     95     char qchar;                 /* character used for quoting attribute values */
     96     xmlParserCtxtPtr ctxt;
     97     int no_doc_free;
     98     xmlDocPtr doc;
     99 };
    100 
    101 static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
    102 static int xmlCmpTextWriterStackEntry(const void *data0,
    103                                       const void *data1);
    104 static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
    105 static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
    106 static int xmlCmpTextWriterNsStackEntry(const void *data0,
    107                                         const void *data1);
    108 static int xmlTextWriterWriteDocCallback(void *context,
    109                                          const xmlChar * str, int len);
    110 static int xmlTextWriterCloseDocCallback(void *context);
    111 
    112 static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
    113 static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
    114                                       const unsigned char *data);
    115 static void xmlTextWriterStartDocumentCallback(void *ctx);
    116 static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
    117 static int
    118   xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
    119                                        xmlTextWriterStackEntry * p);
    120 
    121 /**
    122  * xmlWriterErrMsg:
    123  * @ctxt:  a writer context
    124  * @error:  the error number
    125  * @msg:  the error message
    126  *
    127  * Handle a writer error
    128  */
    129 static void
    130 xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
    131                const char *msg)
    132 {
    133     if (ctxt != NULL) {
    134 	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
    135 	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
    136 		    NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
    137     } else {
    138 	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
    139                     XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
    140     }
    141 }
    142 
    143 /**
    144  * xmlWriterErrMsgInt:
    145  * @ctxt:  a writer context
    146  * @error:  the error number
    147  * @msg:  the error message
    148  * @val:  an int
    149  *
    150  * Handle a writer error
    151  */
    152 static void
    153 xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
    154                const char *msg, int val)
    155 {
    156     if (ctxt != NULL) {
    157 	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
    158 	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
    159 		    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
    160     } else {
    161 	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
    162                     XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
    163     }
    164 }
    165 
    166 /**
    167  * xmlNewTextWriter:
    168  * @out:  an xmlOutputBufferPtr
    169  *
    170  * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
    171  * NOTE: the @out parameter will be deallocated when the writer is closed
    172  *       (if the call succeed.)
    173  *
    174  * Returns the new xmlTextWriterPtr or NULL in case of error
    175  */
    176 xmlTextWriterPtr
    177 xmlNewTextWriter(xmlOutputBufferPtr out)
    178 {
    179     xmlTextWriterPtr ret;
    180 
    181     ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
    182     if (ret == NULL) {
    183         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    184                         "xmlNewTextWriter : out of memory!\n");
    185         return NULL;
    186     }
    187     memset(ret, 0, (size_t) sizeof(xmlTextWriter));
    188 
    189     ret->nodes = xmlListCreate((xmlListDeallocator)
    190                                xmlFreeTextWriterStackEntry,
    191                                (xmlListDataCompare)
    192                                xmlCmpTextWriterStackEntry);
    193     if (ret->nodes == NULL) {
    194         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    195                         "xmlNewTextWriter : out of memory!\n");
    196         xmlFree(ret);
    197         return NULL;
    198     }
    199 
    200     ret->nsstack = xmlListCreate((xmlListDeallocator)
    201                                  xmlFreeTextWriterNsStackEntry,
    202                                  (xmlListDataCompare)
    203                                  xmlCmpTextWriterNsStackEntry);
    204     if (ret->nsstack == NULL) {
    205         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    206                         "xmlNewTextWriter : out of memory!\n");
    207         xmlListDelete(ret->nodes);
    208         xmlFree(ret);
    209         return NULL;
    210     }
    211 
    212     ret->out = out;
    213     ret->ichar = xmlStrdup(BAD_CAST " ");
    214     ret->qchar = '"';
    215 
    216     if (!ret->ichar) {
    217         xmlListDelete(ret->nodes);
    218         xmlListDelete(ret->nsstack);
    219         xmlFree(ret);
    220         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    221                         "xmlNewTextWriter : out of memory!\n");
    222         return NULL;
    223     }
    224 
    225     ret->doc = xmlNewDoc(NULL);
    226 
    227     ret->no_doc_free = 0;
    228 
    229     return ret;
    230 }
    231 
    232 /**
    233  * xmlNewTextWriterFilename:
    234  * @uri:  the URI of the resource for the output
    235  * @compression:  compress the output?
    236  *
    237  * Create a new xmlNewTextWriter structure with @uri as output
    238  *
    239  * Returns the new xmlTextWriterPtr or NULL in case of error
    240  */
    241 xmlTextWriterPtr
    242 xmlNewTextWriterFilename(const char *uri, int compression)
    243 {
    244     xmlTextWriterPtr ret;
    245     xmlOutputBufferPtr out;
    246 
    247     out = xmlOutputBufferCreateFilename(uri, NULL, compression);
    248     if (out == NULL) {
    249         xmlWriterErrMsg(NULL, XML_IO_EIO,
    250                         "xmlNewTextWriterFilename : cannot open uri\n");
    251         return NULL;
    252     }
    253 
    254     ret = xmlNewTextWriter(out);
    255     if (ret == NULL) {
    256         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    257                         "xmlNewTextWriterFilename : out of memory!\n");
    258         xmlOutputBufferClose(out);
    259         return NULL;
    260     }
    261 
    262     ret->indent = 0;
    263     ret->doindent = 0;
    264     return ret;
    265 }
    266 
    267 /**
    268  * xmlNewTextWriterMemory:
    269  * @buf:  xmlBufferPtr
    270  * @compression:  compress the output?
    271  *
    272  * Create a new xmlNewTextWriter structure with @buf as output
    273  * TODO: handle compression
    274  *
    275  * Returns the new xmlTextWriterPtr or NULL in case of error
    276  */
    277 xmlTextWriterPtr
    278 xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
    279 {
    280     xmlTextWriterPtr ret;
    281     xmlOutputBufferPtr out;
    282 
    283 /*::todo handle compression */
    284     out = xmlOutputBufferCreateBuffer(buf, NULL);
    285 
    286     if (out == NULL) {
    287         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    288                         "xmlNewTextWriterMemory : out of memory!\n");
    289         return NULL;
    290     }
    291 
    292     ret = xmlNewTextWriter(out);
    293     if (ret == NULL) {
    294         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
    295                         "xmlNewTextWriterMemory : out of memory!\n");
    296         xmlOutputBufferClose(out);
    297         return NULL;
    298     }
    299 
    300     return ret;
    301 }
    302 
    303 /**
    304  * xmlNewTextWriterPushParser:
    305  * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
    306  * @compression:  compress the output?
    307  *
    308  * Create a new xmlNewTextWriter structure with @ctxt as output
    309  * NOTE: the @ctxt context will be freed with the resulting writer
    310  *       (if the call succeeds).
    311  * TODO: handle compression
    312  *
    313  * Returns the new xmlTextWriterPtr or NULL in case of error
    314  */
    315 xmlTextWriterPtr
    316 xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
    317                            int compression ATTRIBUTE_UNUSED)
    318 {
    319     xmlTextWriterPtr ret;
    320     xmlOutputBufferPtr out;
    321 
    322     if (ctxt == NULL) {
    323         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    324                         "xmlNewTextWriterPushParser : invalid context!\n");
    325         return NULL;
    326     }
    327 
    328     out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
    329                                   xmlTextWriterWriteDocCallback,
    330                                   (xmlOutputCloseCallback)
    331                                   xmlTextWriterCloseDocCallback,
    332                                   (void *) ctxt, NULL);
    333     if (out == NULL) {
    334         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    335                         "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
    336         return NULL;
    337     }
    338 
    339     ret = xmlNewTextWriter(out);
    340     if (ret == NULL) {
    341         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    342                         "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
    343         xmlOutputBufferClose(out);
    344         return NULL;
    345     }
    346 
    347     ret->ctxt = ctxt;
    348 
    349     return ret;
    350 }
    351 
    352 /**
    353  * xmlNewTextWriterDoc:
    354  * @doc: address of a xmlDocPtr to hold the new XML document tree
    355  * @compression:  compress the output?
    356  *
    357  * Create a new xmlNewTextWriter structure with @*doc as output
    358  *
    359  * Returns the new xmlTextWriterPtr or NULL in case of error
    360  */
    361 xmlTextWriterPtr
    362 xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
    363 {
    364     xmlTextWriterPtr ret;
    365     xmlSAXHandler saxHandler;
    366     xmlParserCtxtPtr ctxt;
    367 
    368     memset(&saxHandler, '\0', sizeof(saxHandler));
    369     xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
    370     saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
    371     saxHandler.startElement = xmlSAX2StartElement;
    372     saxHandler.endElement = xmlSAX2EndElement;
    373 
    374     ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
    375     if (ctxt == NULL) {
    376         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    377                 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
    378         return NULL;
    379     }
    380     /*
    381      * For some reason this seems to completely break if node names
    382      * are interned.
    383      */
    384     ctxt->dictNames = 0;
    385 
    386     ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
    387     if (ctxt->myDoc == NULL) {
    388         xmlFreeParserCtxt(ctxt);
    389         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    390                         "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
    391         return NULL;
    392     }
    393 
    394     ret = xmlNewTextWriterPushParser(ctxt, compression);
    395     if (ret == NULL) {
    396         xmlFreeDoc(ctxt->myDoc);
    397         xmlFreeParserCtxt(ctxt);
    398         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    399                 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
    400         return NULL;
    401     }
    402 
    403     xmlSetDocCompressMode(ctxt->myDoc, compression);
    404 
    405     if (doc != NULL) {
    406         *doc = ctxt->myDoc;
    407 	ret->no_doc_free = 1;
    408     }
    409 
    410     return ret;
    411 }
    412 
    413 /**
    414  * xmlNewTextWriterTree:
    415  * @doc: xmlDocPtr
    416  * @node: xmlNodePtr or NULL for doc->children
    417  * @compression:  compress the output?
    418  *
    419  * Create a new xmlNewTextWriter structure with @doc as output
    420  * starting at @node
    421  *
    422  * Returns the new xmlTextWriterPtr or NULL in case of error
    423  */
    424 xmlTextWriterPtr
    425 xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
    426 {
    427     xmlTextWriterPtr ret;
    428     xmlSAXHandler saxHandler;
    429     xmlParserCtxtPtr ctxt;
    430 
    431     if (doc == NULL) {
    432         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    433                         "xmlNewTextWriterTree : invalid document tree!\n");
    434         return NULL;
    435     }
    436 
    437     memset(&saxHandler, '\0', sizeof(saxHandler));
    438     xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
    439     saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
    440     saxHandler.startElement = xmlSAX2StartElement;
    441     saxHandler.endElement = xmlSAX2EndElement;
    442 
    443     ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
    444     if (ctxt == NULL) {
    445         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    446                         "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
    447         return NULL;
    448     }
    449     /*
    450      * For some reason this seems to completely break if node names
    451      * are interned.
    452      */
    453     ctxt->dictNames = 0;
    454 
    455     ret = xmlNewTextWriterPushParser(ctxt, compression);
    456     if (ret == NULL) {
    457         xmlFreeParserCtxt(ctxt);
    458         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
    459                         "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
    460         return NULL;
    461     }
    462 
    463     ctxt->myDoc = doc;
    464     ctxt->node = node;
    465     ret->no_doc_free = 1;
    466 
    467     xmlSetDocCompressMode(doc, compression);
    468 
    469     return ret;
    470 }
    471 
    472 /**
    473  * xmlFreeTextWriter:
    474  * @writer:  the xmlTextWriterPtr
    475  *
    476  * Deallocate all the resources associated to the writer
    477  */
    478 void
    479 xmlFreeTextWriter(xmlTextWriterPtr writer)
    480 {
    481     if (writer == NULL)
    482         return;
    483 
    484     if (writer->out != NULL)
    485         xmlOutputBufferClose(writer->out);
    486 
    487     if (writer->nodes != NULL)
    488         xmlListDelete(writer->nodes);
    489 
    490     if (writer->nsstack != NULL)
    491         xmlListDelete(writer->nsstack);
    492 
    493     if (writer->ctxt != NULL) {
    494         if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
    495 	    xmlFreeDoc(writer->ctxt->myDoc);
    496 	    writer->ctxt->myDoc = NULL;
    497 	}
    498         xmlFreeParserCtxt(writer->ctxt);
    499     }
    500 
    501     if (writer->doc != NULL)
    502         xmlFreeDoc(writer->doc);
    503 
    504     if (writer->ichar != NULL)
    505         xmlFree(writer->ichar);
    506     xmlFree(writer);
    507 }
    508 
    509 /**
    510  * xmlTextWriterStartDocument:
    511  * @writer:  the xmlTextWriterPtr
    512  * @version:  the xml version ("1.0") or NULL for default ("1.0")
    513  * @encoding:  the encoding or NULL for default
    514  * @standalone: "yes" or "no" or NULL for default
    515  *
    516  * Start a new xml document
    517  *
    518  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    519  */
    520 int
    521 xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
    522                            const char *encoding, const char *standalone)
    523 {
    524     int count;
    525     int sum;
    526     xmlLinkPtr lk;
    527     xmlCharEncodingHandlerPtr encoder;
    528 
    529     if ((writer == NULL) || (writer->out == NULL)) {
    530         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    531                         "xmlTextWriterStartDocument : invalid writer!\n");
    532         return -1;
    533     }
    534 
    535     lk = xmlListFront(writer->nodes);
    536     if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
    537         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    538                         "xmlTextWriterStartDocument : not allowed in this context!\n");
    539         return -1;
    540     }
    541 
    542     encoder = NULL;
    543     if (encoding != NULL) {
    544         encoder = xmlFindCharEncodingHandler(encoding);
    545         if (encoder == NULL) {
    546             xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
    547                             "xmlTextWriterStartDocument : out of memory!\n");
    548             return -1;
    549         }
    550     }
    551 
    552     writer->out->encoder = encoder;
    553     if (encoder != NULL) {
    554 	if (writer->out->conv == NULL) {
    555 	    writer->out->conv = xmlBufCreateSize(4000);
    556 	}
    557         xmlCharEncOutput(writer->out, 1);
    558         if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
    559             writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
    560     } else
    561         writer->out->conv = NULL;
    562 
    563     sum = 0;
    564     count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
    565     if (count < 0)
    566         return -1;
    567     sum += count;
    568     count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
    569     if (count < 0)
    570         return -1;
    571     sum += count;
    572     if (version != 0)
    573         count = xmlOutputBufferWriteString(writer->out, version);
    574     else
    575         count = xmlOutputBufferWriteString(writer->out, "1.0");
    576     if (count < 0)
    577         return -1;
    578     sum += count;
    579     count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
    580     if (count < 0)
    581         return -1;
    582     sum += count;
    583     if (writer->out->encoder != 0) {
    584         count = xmlOutputBufferWriteString(writer->out, " encoding=");
    585         if (count < 0)
    586             return -1;
    587         sum += count;
    588         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
    589         if (count < 0)
    590             return -1;
    591         sum += count;
    592         count =
    593             xmlOutputBufferWriteString(writer->out,
    594                                        writer->out->encoder->name);
    595         if (count < 0)
    596             return -1;
    597         sum += count;
    598         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
    599         if (count < 0)
    600             return -1;
    601         sum += count;
    602     }
    603 
    604     if (standalone != 0) {
    605         count = xmlOutputBufferWriteString(writer->out, " standalone=");
    606         if (count < 0)
    607             return -1;
    608         sum += count;
    609         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
    610         if (count < 0)
    611             return -1;
    612         sum += count;
    613         count = xmlOutputBufferWriteString(writer->out, standalone);
    614         if (count < 0)
    615             return -1;
    616         sum += count;
    617         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
    618         if (count < 0)
    619             return -1;
    620         sum += count;
    621     }
    622 
    623     count = xmlOutputBufferWriteString(writer->out, "?>\n");
    624     if (count < 0)
    625         return -1;
    626     sum += count;
    627 
    628     return sum;
    629 }
    630 
    631 /**
    632  * xmlTextWriterEndDocument:
    633  * @writer:  the xmlTextWriterPtr
    634  *
    635  * End an xml document. All open elements are closed, and
    636  * the content is flushed to the output.
    637  *
    638  * Returns the bytes written or -1 in case of error
    639  */
    640 int
    641 xmlTextWriterEndDocument(xmlTextWriterPtr writer)
    642 {
    643     int count;
    644     int sum;
    645     xmlLinkPtr lk;
    646     xmlTextWriterStackEntry *p;
    647 
    648     if (writer == NULL) {
    649         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    650                         "xmlTextWriterEndDocument : invalid writer!\n");
    651         return -1;
    652     }
    653 
    654     sum = 0;
    655     while ((lk = xmlListFront(writer->nodes)) != NULL) {
    656         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
    657         if (p == 0)
    658             break;
    659         switch (p->state) {
    660             case XML_TEXTWRITER_NAME:
    661             case XML_TEXTWRITER_ATTRIBUTE:
    662             case XML_TEXTWRITER_TEXT:
    663                 count = xmlTextWriterEndElement(writer);
    664                 if (count < 0)
    665                     return -1;
    666                 sum += count;
    667                 break;
    668             case XML_TEXTWRITER_PI:
    669             case XML_TEXTWRITER_PI_TEXT:
    670                 count = xmlTextWriterEndPI(writer);
    671                 if (count < 0)
    672                     return -1;
    673                 sum += count;
    674                 break;
    675             case XML_TEXTWRITER_CDATA:
    676                 count = xmlTextWriterEndCDATA(writer);
    677                 if (count < 0)
    678                     return -1;
    679                 sum += count;
    680                 break;
    681             case XML_TEXTWRITER_DTD:
    682             case XML_TEXTWRITER_DTD_TEXT:
    683             case XML_TEXTWRITER_DTD_ELEM:
    684             case XML_TEXTWRITER_DTD_ELEM_TEXT:
    685             case XML_TEXTWRITER_DTD_ATTL:
    686             case XML_TEXTWRITER_DTD_ATTL_TEXT:
    687             case XML_TEXTWRITER_DTD_ENTY:
    688             case XML_TEXTWRITER_DTD_ENTY_TEXT:
    689             case XML_TEXTWRITER_DTD_PENT:
    690                 count = xmlTextWriterEndDTD(writer);
    691                 if (count < 0)
    692                     return -1;
    693                 sum += count;
    694                 break;
    695             case XML_TEXTWRITER_COMMENT:
    696                 count = xmlTextWriterEndComment(writer);
    697                 if (count < 0)
    698                     return -1;
    699                 sum += count;
    700                 break;
    701             default:
    702                 break;
    703         }
    704     }
    705 
    706     if (!writer->indent) {
    707         count = xmlOutputBufferWriteString(writer->out, "\n");
    708         if (count < 0)
    709             return -1;
    710         sum += count;
    711     }
    712 
    713     sum += xmlTextWriterFlush(writer);
    714 
    715     return sum;
    716 }
    717 
    718 /**
    719  * xmlTextWriterStartComment:
    720  * @writer:  the xmlTextWriterPtr
    721  *
    722  * Start an xml comment.
    723  *
    724  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    725  */
    726 int
    727 xmlTextWriterStartComment(xmlTextWriterPtr writer)
    728 {
    729     int count;
    730     int sum;
    731     xmlLinkPtr lk;
    732     xmlTextWriterStackEntry *p;
    733 
    734     if (writer == NULL) {
    735         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    736                         "xmlTextWriterStartComment : invalid writer!\n");
    737         return -1;
    738     }
    739 
    740     sum = 0;
    741     lk = xmlListFront(writer->nodes);
    742     if (lk != 0) {
    743         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
    744         if (p != 0) {
    745             switch (p->state) {
    746                 case XML_TEXTWRITER_TEXT:
    747                 case XML_TEXTWRITER_NONE:
    748                     break;
    749                 case XML_TEXTWRITER_NAME:
    750                     /* Output namespace declarations */
    751                     count = xmlTextWriterOutputNSDecl(writer);
    752                     if (count < 0)
    753                         return -1;
    754                     sum += count;
    755                     count = xmlOutputBufferWriteString(writer->out, ">");
    756                     if (count < 0)
    757                         return -1;
    758                     sum += count;
    759                     if (writer->indent) {
    760                         count =
    761                             xmlOutputBufferWriteString(writer->out, "\n");
    762                         if (count < 0)
    763                             return -1;
    764                         sum += count;
    765                     }
    766                     p->state = XML_TEXTWRITER_TEXT;
    767                     break;
    768                 default:
    769                     return -1;
    770             }
    771         }
    772     }
    773 
    774     p = (xmlTextWriterStackEntry *)
    775         xmlMalloc(sizeof(xmlTextWriterStackEntry));
    776     if (p == 0) {
    777         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
    778                         "xmlTextWriterStartElement : out of memory!\n");
    779         return -1;
    780     }
    781 
    782     p->name = NULL;
    783     p->state = XML_TEXTWRITER_COMMENT;
    784 
    785     xmlListPushFront(writer->nodes, p);
    786 
    787     if (writer->indent) {
    788         count = xmlTextWriterWriteIndent(writer);
    789         if (count < 0)
    790             return -1;
    791         sum += count;
    792     }
    793 
    794     count = xmlOutputBufferWriteString(writer->out, "<!--");
    795     if (count < 0)
    796         return -1;
    797     sum += count;
    798 
    799     return sum;
    800 }
    801 
    802 /**
    803  * xmlTextWriterEndComment:
    804  * @writer:  the xmlTextWriterPtr
    805  *
    806  * End the current xml coment.
    807  *
    808  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    809  */
    810 int
    811 xmlTextWriterEndComment(xmlTextWriterPtr writer)
    812 {
    813     int count;
    814     int sum;
    815     xmlLinkPtr lk;
    816     xmlTextWriterStackEntry *p;
    817 
    818     if (writer == NULL) {
    819         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    820                         "xmlTextWriterEndComment : invalid writer!\n");
    821         return -1;
    822     }
    823 
    824     lk = xmlListFront(writer->nodes);
    825     if (lk == 0) {
    826         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    827                         "xmlTextWriterEndComment : not allowed in this context!\n");
    828         return -1;
    829     }
    830 
    831     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
    832     if (p == 0)
    833         return -1;
    834 
    835     sum = 0;
    836     switch (p->state) {
    837         case XML_TEXTWRITER_COMMENT:
    838             count = xmlOutputBufferWriteString(writer->out, "-->");
    839             if (count < 0)
    840                 return -1;
    841             sum += count;
    842             break;
    843         default:
    844             return -1;
    845     }
    846 
    847     if (writer->indent) {
    848         count = xmlOutputBufferWriteString(writer->out, "\n");
    849         if (count < 0)
    850             return -1;
    851         sum += count;
    852     }
    853 
    854     xmlListPopFront(writer->nodes);
    855     return sum;
    856 }
    857 
    858 /**
    859  * xmlTextWriterWriteFormatComment:
    860  * @writer:  the xmlTextWriterPtr
    861  * @format:  format string (see printf)
    862  * @...:  extra parameters for the format
    863  *
    864  * Write an xml comment.
    865  *
    866  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    867  */
    868 int XMLCDECL
    869 xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
    870                                 const char *format, ...)
    871 {
    872     int rc;
    873     va_list ap;
    874 
    875     va_start(ap, format);
    876 
    877     rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
    878 
    879     va_end(ap);
    880     return rc;
    881 }
    882 
    883 /**
    884  * xmlTextWriterWriteVFormatComment:
    885  * @writer:  the xmlTextWriterPtr
    886  * @format:  format string (see printf)
    887  * @argptr:  pointer to the first member of the variable argument list.
    888  *
    889  * Write an xml comment.
    890  *
    891  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    892  */
    893 int
    894 xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
    895                                  const char *format, va_list argptr)
    896 {
    897     int rc;
    898     xmlChar *buf;
    899 
    900     if (writer == NULL) {
    901         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
    902                         "xmlTextWriterWriteVFormatComment : invalid writer!\n");
    903         return -1;
    904     }
    905 
    906     buf = xmlTextWriterVSprintf(format, argptr);
    907     if (buf == NULL)
    908         return -1;
    909 
    910     rc = xmlTextWriterWriteComment(writer, buf);
    911 
    912     xmlFree(buf);
    913     return rc;
    914 }
    915 
    916 /**
    917  * xmlTextWriterWriteComment:
    918  * @writer:  the xmlTextWriterPtr
    919  * @content:  comment string
    920  *
    921  * Write an xml comment.
    922  *
    923  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    924  */
    925 int
    926 xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
    927 {
    928     int count;
    929     int sum;
    930 
    931     sum = 0;
    932     count = xmlTextWriterStartComment(writer);
    933     if (count < 0)
    934         return -1;
    935     sum += count;
    936     count = xmlTextWriterWriteString(writer, content);
    937     if (count < 0)
    938         return -1;
    939     sum += count;
    940     count = xmlTextWriterEndComment(writer);
    941     if (count < 0)
    942         return -1;
    943     sum += count;
    944 
    945     return sum;
    946 }
    947 
    948 /**
    949  * xmlTextWriterStartElement:
    950  * @writer:  the xmlTextWriterPtr
    951  * @name:  element name
    952  *
    953  * Start an xml element.
    954  *
    955  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
    956  */
    957 int
    958 xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
    959 {
    960     int count;
    961     int sum;
    962     xmlLinkPtr lk;
    963     xmlTextWriterStackEntry *p;
    964 
    965     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
    966         return -1;
    967 
    968     sum = 0;
    969     lk = xmlListFront(writer->nodes);
    970     if (lk != 0) {
    971         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
    972         if (p != 0) {
    973             switch (p->state) {
    974                 case XML_TEXTWRITER_PI:
    975                 case XML_TEXTWRITER_PI_TEXT:
    976                     return -1;
    977                 case XML_TEXTWRITER_NONE:
    978                     break;
    979 				case XML_TEXTWRITER_ATTRIBUTE:
    980 					count = xmlTextWriterEndAttribute(writer);
    981 					if (count < 0)
    982 						return -1;
    983 					sum += count;
    984 					/* fallthrough */
    985                 case XML_TEXTWRITER_NAME:
    986                     /* Output namespace declarations */
    987                     count = xmlTextWriterOutputNSDecl(writer);
    988                     if (count < 0)
    989                         return -1;
    990                     sum += count;
    991                     count = xmlOutputBufferWriteString(writer->out, ">");
    992                     if (count < 0)
    993                         return -1;
    994                     sum += count;
    995                     if (writer->indent)
    996                         count =
    997                             xmlOutputBufferWriteString(writer->out, "\n");
    998                     p->state = XML_TEXTWRITER_TEXT;
    999                     break;
   1000                 default:
   1001                     break;
   1002             }
   1003         }
   1004     }
   1005 
   1006     p = (xmlTextWriterStackEntry *)
   1007         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   1008     if (p == 0) {
   1009         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   1010                         "xmlTextWriterStartElement : out of memory!\n");
   1011         return -1;
   1012     }
   1013 
   1014     p->name = xmlStrdup(name);
   1015     if (p->name == 0) {
   1016         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   1017                         "xmlTextWriterStartElement : out of memory!\n");
   1018         xmlFree(p);
   1019         return -1;
   1020     }
   1021     p->state = XML_TEXTWRITER_NAME;
   1022 
   1023     xmlListPushFront(writer->nodes, p);
   1024 
   1025     if (writer->indent) {
   1026         count = xmlTextWriterWriteIndent(writer);
   1027         sum += count;
   1028     }
   1029 
   1030     count = xmlOutputBufferWriteString(writer->out, "<");
   1031     if (count < 0)
   1032         return -1;
   1033     sum += count;
   1034     count =
   1035         xmlOutputBufferWriteString(writer->out, (const char *) p->name);
   1036     if (count < 0)
   1037         return -1;
   1038     sum += count;
   1039 
   1040     return sum;
   1041 }
   1042 
   1043 /**
   1044  * xmlTextWriterStartElementNS:
   1045  * @writer:  the xmlTextWriterPtr
   1046  * @prefix:  namespace prefix or NULL
   1047  * @name:  element local name
   1048  * @namespaceURI:  namespace URI or NULL
   1049  *
   1050  * Start an xml element with namespace support.
   1051  *
   1052  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1053  */
   1054 int
   1055 xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
   1056                             const xmlChar * prefix, const xmlChar * name,
   1057                             const xmlChar * namespaceURI)
   1058 {
   1059     int count;
   1060     int sum;
   1061     xmlChar *buf;
   1062 
   1063     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
   1064         return -1;
   1065 
   1066     buf = NULL;
   1067     if (prefix != 0) {
   1068         buf = xmlStrdup(prefix);
   1069         buf = xmlStrcat(buf, BAD_CAST ":");
   1070     }
   1071     buf = xmlStrcat(buf, name);
   1072 
   1073     sum = 0;
   1074     count = xmlTextWriterStartElement(writer, buf);
   1075     xmlFree(buf);
   1076     if (count < 0)
   1077         return -1;
   1078     sum += count;
   1079 
   1080     if (namespaceURI != 0) {
   1081         xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
   1082         xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
   1083         if (p == 0) {
   1084             xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   1085                             "xmlTextWriterStartElementNS : out of memory!\n");
   1086             return -1;
   1087         }
   1088 
   1089         buf = xmlStrdup(BAD_CAST "xmlns");
   1090         if (prefix != 0) {
   1091             buf = xmlStrcat(buf, BAD_CAST ":");
   1092             buf = xmlStrcat(buf, prefix);
   1093         }
   1094 
   1095         p->prefix = buf;
   1096         p->uri = xmlStrdup(namespaceURI);
   1097         if (p->uri == 0) {
   1098             xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   1099                             "xmlTextWriterStartElementNS : out of memory!\n");
   1100             xmlFree(p);
   1101             return -1;
   1102         }
   1103         p->elem = xmlListFront(writer->nodes);
   1104 
   1105         xmlListPushFront(writer->nsstack, p);
   1106     }
   1107 
   1108     return sum;
   1109 }
   1110 
   1111 /**
   1112  * xmlTextWriterEndElement:
   1113  * @writer:  the xmlTextWriterPtr
   1114  *
   1115  * End the current xml element.
   1116  *
   1117  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1118  */
   1119 int
   1120 xmlTextWriterEndElement(xmlTextWriterPtr writer)
   1121 {
   1122     int count;
   1123     int sum;
   1124     xmlLinkPtr lk;
   1125     xmlTextWriterStackEntry *p;
   1126 
   1127     if (writer == NULL)
   1128         return -1;
   1129 
   1130     lk = xmlListFront(writer->nodes);
   1131     if (lk == 0) {
   1132         xmlListDelete(writer->nsstack);
   1133         writer->nsstack = NULL;
   1134         return -1;
   1135     }
   1136 
   1137     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1138     if (p == 0) {
   1139         xmlListDelete(writer->nsstack);
   1140         writer->nsstack = NULL;
   1141         return -1;
   1142     }
   1143 
   1144     sum = 0;
   1145     switch (p->state) {
   1146         case XML_TEXTWRITER_ATTRIBUTE:
   1147             count = xmlTextWriterEndAttribute(writer);
   1148             if (count < 0) {
   1149                 xmlListDelete(writer->nsstack);
   1150                 writer->nsstack = NULL;
   1151                 return -1;
   1152             }
   1153             sum += count;
   1154             /* fallthrough */
   1155         case XML_TEXTWRITER_NAME:
   1156             /* Output namespace declarations */
   1157             count = xmlTextWriterOutputNSDecl(writer);
   1158             if (count < 0)
   1159                 return -1;
   1160             sum += count;
   1161 
   1162             if (writer->indent) /* next element needs indent */
   1163                 writer->doindent = 1;
   1164             count = xmlOutputBufferWriteString(writer->out, "/>");
   1165             if (count < 0)
   1166                 return -1;
   1167             sum += count;
   1168             break;
   1169         case XML_TEXTWRITER_TEXT:
   1170             if ((writer->indent) && (writer->doindent)) {
   1171                 count = xmlTextWriterWriteIndent(writer);
   1172                 sum += count;
   1173                 writer->doindent = 1;
   1174             } else
   1175                 writer->doindent = 1;
   1176             count = xmlOutputBufferWriteString(writer->out, "</");
   1177             if (count < 0)
   1178                 return -1;
   1179             sum += count;
   1180             count = xmlOutputBufferWriteString(writer->out,
   1181                                                (const char *) p->name);
   1182             if (count < 0)
   1183                 return -1;
   1184             sum += count;
   1185             count = xmlOutputBufferWriteString(writer->out, ">");
   1186             if (count < 0)
   1187                 return -1;
   1188             sum += count;
   1189             break;
   1190         default:
   1191             return -1;
   1192     }
   1193 
   1194     if (writer->indent) {
   1195         count = xmlOutputBufferWriteString(writer->out, "\n");
   1196         sum += count;
   1197     }
   1198 
   1199     xmlListPopFront(writer->nodes);
   1200     return sum;
   1201 }
   1202 
   1203 /**
   1204  * xmlTextWriterFullEndElement:
   1205  * @writer:  the xmlTextWriterPtr
   1206  *
   1207  * End the current xml element. Writes an end tag even if the element is empty
   1208  *
   1209  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1210  */
   1211 int
   1212 xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
   1213 {
   1214     int count;
   1215     int sum;
   1216     xmlLinkPtr lk;
   1217     xmlTextWriterStackEntry *p;
   1218 
   1219     if (writer == NULL)
   1220         return -1;
   1221 
   1222     lk = xmlListFront(writer->nodes);
   1223     if (lk == 0)
   1224         return -1;
   1225 
   1226     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1227     if (p == 0)
   1228         return -1;
   1229 
   1230     sum = 0;
   1231     switch (p->state) {
   1232         case XML_TEXTWRITER_ATTRIBUTE:
   1233             count = xmlTextWriterEndAttribute(writer);
   1234             if (count < 0)
   1235                 return -1;
   1236             sum += count;
   1237             /* fallthrough */
   1238         case XML_TEXTWRITER_NAME:
   1239             /* Output namespace declarations */
   1240             count = xmlTextWriterOutputNSDecl(writer);
   1241             if (count < 0)
   1242                 return -1;
   1243             sum += count;
   1244 
   1245             count = xmlOutputBufferWriteString(writer->out, ">");
   1246             if (count < 0)
   1247                 return -1;
   1248             sum += count;
   1249             if (writer->indent)
   1250                 writer->doindent = 0;
   1251             /* fallthrough */
   1252         case XML_TEXTWRITER_TEXT:
   1253             if ((writer->indent) && (writer->doindent)) {
   1254                 count = xmlTextWriterWriteIndent(writer);
   1255                 sum += count;
   1256                 writer->doindent = 1;
   1257             } else
   1258                 writer->doindent = 1;
   1259             count = xmlOutputBufferWriteString(writer->out, "</");
   1260             if (count < 0)
   1261                 return -1;
   1262             sum += count;
   1263             count = xmlOutputBufferWriteString(writer->out,
   1264                                                (const char *) p->name);
   1265             if (count < 0)
   1266                 return -1;
   1267             sum += count;
   1268             count = xmlOutputBufferWriteString(writer->out, ">");
   1269             if (count < 0)
   1270                 return -1;
   1271             sum += count;
   1272             break;
   1273         default:
   1274             return -1;
   1275     }
   1276 
   1277     if (writer->indent) {
   1278         count = xmlOutputBufferWriteString(writer->out, "\n");
   1279         sum += count;
   1280     }
   1281 
   1282     xmlListPopFront(writer->nodes);
   1283     return sum;
   1284 }
   1285 
   1286 /**
   1287  * xmlTextWriterWriteFormatRaw:
   1288  * @writer:  the xmlTextWriterPtr
   1289  * @format:  format string (see printf)
   1290  * @...:  extra parameters for the format
   1291  *
   1292  * Write a formatted raw xml text.
   1293  *
   1294  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1295  */
   1296 int XMLCDECL
   1297 xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
   1298                             ...)
   1299 {
   1300     int rc;
   1301     va_list ap;
   1302 
   1303     va_start(ap, format);
   1304 
   1305     rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
   1306 
   1307     va_end(ap);
   1308     return rc;
   1309 }
   1310 
   1311 /**
   1312  * xmlTextWriterWriteVFormatRaw:
   1313  * @writer:  the xmlTextWriterPtr
   1314  * @format:  format string (see printf)
   1315  * @argptr:  pointer to the first member of the variable argument list.
   1316  *
   1317  * Write a formatted raw xml text.
   1318  *
   1319  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1320  */
   1321 int
   1322 xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
   1323                              va_list argptr)
   1324 {
   1325     int rc;
   1326     xmlChar *buf;
   1327 
   1328     if (writer == NULL)
   1329         return -1;
   1330 
   1331     buf = xmlTextWriterVSprintf(format, argptr);
   1332     if (buf == NULL)
   1333         return -1;
   1334 
   1335     rc = xmlTextWriterWriteRaw(writer, buf);
   1336 
   1337     xmlFree(buf);
   1338     return rc;
   1339 }
   1340 
   1341 /**
   1342  * xmlTextWriterWriteRawLen:
   1343  * @writer:  the xmlTextWriterPtr
   1344  * @content:  text string
   1345  * @len:  length of the text string
   1346  *
   1347  * Write an xml text.
   1348  * TODO: what about entities and special chars??
   1349  *
   1350  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1351  */
   1352 int
   1353 xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
   1354                          int len)
   1355 {
   1356     int count;
   1357     int sum;
   1358     xmlLinkPtr lk;
   1359     xmlTextWriterStackEntry *p;
   1360 
   1361     if (writer == NULL) {
   1362         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   1363                         "xmlTextWriterWriteRawLen : invalid writer!\n");
   1364         return -1;
   1365     }
   1366 
   1367     if ((content == NULL) || (len < 0)) {
   1368         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   1369                         "xmlTextWriterWriteRawLen : invalid content!\n");
   1370         return -1;
   1371     }
   1372 
   1373     sum = 0;
   1374     lk = xmlListFront(writer->nodes);
   1375     if (lk != 0) {
   1376         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1377         count = xmlTextWriterHandleStateDependencies(writer, p);
   1378         if (count < 0)
   1379             return -1;
   1380         sum += count;
   1381     }
   1382 
   1383     if (writer->indent)
   1384         writer->doindent = 0;
   1385 
   1386     if (content != NULL) {
   1387         count =
   1388             xmlOutputBufferWrite(writer->out, len, (const char *) content);
   1389         if (count < 0)
   1390             return -1;
   1391         sum += count;
   1392     }
   1393 
   1394     return sum;
   1395 }
   1396 
   1397 /**
   1398  * xmlTextWriterWriteRaw:
   1399  * @writer:  the xmlTextWriterPtr
   1400  * @content:  text string
   1401  *
   1402  * Write a raw xml text.
   1403  *
   1404  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1405  */
   1406 int
   1407 xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
   1408 {
   1409     return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
   1410 }
   1411 
   1412 /**
   1413  * xmlTextWriterWriteFormatString:
   1414  * @writer:  the xmlTextWriterPtr
   1415  * @format:  format string (see printf)
   1416  * @...:  extra parameters for the format
   1417  *
   1418  * Write a formatted xml text.
   1419  *
   1420  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1421  */
   1422 int XMLCDECL
   1423 xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
   1424                                ...)
   1425 {
   1426     int rc;
   1427     va_list ap;
   1428 
   1429     if ((writer == NULL) || (format == NULL))
   1430         return -1;
   1431 
   1432     va_start(ap, format);
   1433 
   1434     rc = xmlTextWriterWriteVFormatString(writer, format, ap);
   1435 
   1436     va_end(ap);
   1437     return rc;
   1438 }
   1439 
   1440 /**
   1441  * xmlTextWriterWriteVFormatString:
   1442  * @writer:  the xmlTextWriterPtr
   1443  * @format:  format string (see printf)
   1444  * @argptr:  pointer to the first member of the variable argument list.
   1445  *
   1446  * Write a formatted xml text.
   1447  *
   1448  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1449  */
   1450 int
   1451 xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
   1452                                 const char *format, va_list argptr)
   1453 {
   1454     int rc;
   1455     xmlChar *buf;
   1456 
   1457     if ((writer == NULL) || (format == NULL))
   1458         return -1;
   1459 
   1460     buf = xmlTextWriterVSprintf(format, argptr);
   1461     if (buf == NULL)
   1462         return -1;
   1463 
   1464     rc = xmlTextWriterWriteString(writer, buf);
   1465 
   1466     xmlFree(buf);
   1467     return rc;
   1468 }
   1469 
   1470 /**
   1471  * xmlTextWriterWriteString:
   1472  * @writer:  the xmlTextWriterPtr
   1473  * @content:  text string
   1474  *
   1475  * Write an xml text.
   1476  *
   1477  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1478  */
   1479 int
   1480 xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
   1481 {
   1482     int count;
   1483     int sum;
   1484     xmlLinkPtr lk;
   1485     xmlTextWriterStackEntry *p;
   1486     xmlChar *buf;
   1487 
   1488     if ((writer == NULL) || (content == NULL))
   1489         return -1;
   1490 
   1491     sum = 0;
   1492     buf = (xmlChar *) content;
   1493     lk = xmlListFront(writer->nodes);
   1494     if (lk != 0) {
   1495         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1496         if (p != 0) {
   1497             switch (p->state) {
   1498                 case XML_TEXTWRITER_NAME:
   1499                 case XML_TEXTWRITER_TEXT:
   1500 #if 0
   1501                     buf = NULL;
   1502 		    xmlOutputBufferWriteEscape(writer->out, content, NULL);
   1503 #endif
   1504                     buf = xmlEncodeSpecialChars(NULL, content);
   1505                     break;
   1506                 case XML_TEXTWRITER_ATTRIBUTE:
   1507                     buf = NULL;
   1508                     xmlBufAttrSerializeTxtContent(writer->out->buffer,
   1509                                                   writer->doc, NULL, content);
   1510                     break;
   1511 		default:
   1512 		    break;
   1513             }
   1514         }
   1515     }
   1516 
   1517     if (buf != NULL) {
   1518         count = xmlTextWriterWriteRaw(writer, buf);
   1519 
   1520         if (buf != content)     /* buf was allocated by us, so free it */
   1521             xmlFree(buf);
   1522 
   1523         if (count < 0)
   1524             return -1;
   1525         sum += count;
   1526     }
   1527 
   1528     return sum;
   1529 }
   1530 
   1531 /**
   1532  * xmlOutputBufferWriteBase64:
   1533  * @out: the xmlOutputBufferPtr
   1534  * @data:   binary data
   1535  * @len:  the number of bytes to encode
   1536  *
   1537  * Write base64 encoded data to an xmlOutputBuffer.
   1538  * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
   1539  *
   1540  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1541  */
   1542 static int
   1543 xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
   1544                            const unsigned char *data)
   1545 {
   1546     static unsigned char dtable[64] =
   1547             {'A','B','C','D','E','F','G','H','I','J','K','L','M',
   1548 	     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
   1549 	     'a','b','c','d','e','f','g','h','i','j','k','l','m',
   1550 	     'n','o','p','q','r','s','t','u','v','w','x','y','z',
   1551 	     '0','1','2','3','4','5','6','7','8','9','+','/'};
   1552 
   1553     int i;
   1554     int linelen;
   1555     int count;
   1556     int sum;
   1557 
   1558     if ((out == NULL) || (len < 0) || (data == NULL))
   1559         return(-1);
   1560 
   1561     linelen = 0;
   1562     sum = 0;
   1563 
   1564     i = 0;
   1565     while (1) {
   1566         unsigned char igroup[3];
   1567         unsigned char ogroup[4];
   1568         int c;
   1569         int n;
   1570 
   1571         igroup[0] = igroup[1] = igroup[2] = 0;
   1572         for (n = 0; n < 3 && i < len; n++, i++) {
   1573             c = data[i];
   1574             igroup[n] = (unsigned char) c;
   1575         }
   1576 
   1577         if (n > 0) {
   1578             ogroup[0] = dtable[igroup[0] >> 2];
   1579             ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
   1580             ogroup[2] =
   1581                 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
   1582             ogroup[3] = dtable[igroup[2] & 0x3F];
   1583 
   1584             if (n < 3) {
   1585                 ogroup[3] = '=';
   1586                 if (n < 2) {
   1587                     ogroup[2] = '=';
   1588                 }
   1589             }
   1590 
   1591             if (linelen >= B64LINELEN) {
   1592                 count = xmlOutputBufferWrite(out, 2, B64CRLF);
   1593                 if (count == -1)
   1594                     return -1;
   1595                 sum += count;
   1596                 linelen = 0;
   1597             }
   1598             count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
   1599             if (count == -1)
   1600                 return -1;
   1601             sum += count;
   1602 
   1603             linelen += 4;
   1604         }
   1605 
   1606         if (i >= len)
   1607             break;
   1608     }
   1609 
   1610     return sum;
   1611 }
   1612 
   1613 /**
   1614  * xmlTextWriterWriteBase64:
   1615  * @writer: the xmlTextWriterPtr
   1616  * @data:   binary data
   1617  * @start:  the position within the data of the first byte to encode
   1618  * @len:  the number of bytes to encode
   1619  *
   1620  * Write an base64 encoded xml text.
   1621  *
   1622  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1623  */
   1624 int
   1625 xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
   1626                          int start, int len)
   1627 {
   1628     int count;
   1629     int sum;
   1630     xmlLinkPtr lk;
   1631     xmlTextWriterStackEntry *p;
   1632 
   1633     if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
   1634         return -1;
   1635 
   1636     sum = 0;
   1637     lk = xmlListFront(writer->nodes);
   1638     if (lk != 0) {
   1639         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1640         if (p != 0) {
   1641             count = xmlTextWriterHandleStateDependencies(writer, p);
   1642             if (count < 0)
   1643                 return -1;
   1644             sum += count;
   1645         }
   1646     }
   1647 
   1648     if (writer->indent)
   1649         writer->doindent = 0;
   1650 
   1651     count =
   1652         xmlOutputBufferWriteBase64(writer->out, len,
   1653                                    (unsigned char *) data + start);
   1654     if (count < 0)
   1655         return -1;
   1656     sum += count;
   1657 
   1658     return sum;
   1659 }
   1660 
   1661 /**
   1662  * xmlOutputBufferWriteBinHex:
   1663  * @out: the xmlOutputBufferPtr
   1664  * @data:   binary data
   1665  * @len:  the number of bytes to encode
   1666  *
   1667  * Write hqx encoded data to an xmlOutputBuffer.
   1668  * ::todo
   1669  *
   1670  * Returns the bytes written (may be 0 because of buffering)
   1671  * or -1 in case of error
   1672  */
   1673 static int
   1674 xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
   1675                            int len, const unsigned char *data)
   1676 {
   1677     int count;
   1678     int sum;
   1679     static char hex[16] =
   1680 	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
   1681     int i;
   1682 
   1683     if ((out == NULL) || (data == NULL) || (len < 0)) {
   1684         return -1;
   1685     }
   1686 
   1687     sum = 0;
   1688     for (i = 0; i < len; i++) {
   1689         count =
   1690             xmlOutputBufferWrite(out, 1,
   1691                                  (const char *) &hex[data[i] >> 4]);
   1692         if (count == -1)
   1693             return -1;
   1694         sum += count;
   1695         count =
   1696             xmlOutputBufferWrite(out, 1,
   1697                                  (const char *) &hex[data[i] & 0xF]);
   1698         if (count == -1)
   1699             return -1;
   1700         sum += count;
   1701     }
   1702 
   1703     return sum;
   1704 }
   1705 
   1706 /**
   1707  * xmlTextWriterWriteBinHex:
   1708  * @writer: the xmlTextWriterPtr
   1709  * @data:   binary data
   1710  * @start:  the position within the data of the first byte to encode
   1711  * @len:  the number of bytes to encode
   1712  *
   1713  * Write a BinHex encoded xml text.
   1714  *
   1715  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1716  */
   1717 int
   1718 xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
   1719                          int start, int len)
   1720 {
   1721     int count;
   1722     int sum;
   1723     xmlLinkPtr lk;
   1724     xmlTextWriterStackEntry *p;
   1725 
   1726     if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
   1727         return -1;
   1728 
   1729     sum = 0;
   1730     lk = xmlListFront(writer->nodes);
   1731     if (lk != 0) {
   1732         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1733         if (p != 0) {
   1734             count = xmlTextWriterHandleStateDependencies(writer, p);
   1735             if (count < 0)
   1736                 return -1;
   1737             sum += count;
   1738         }
   1739     }
   1740 
   1741     if (writer->indent)
   1742         writer->doindent = 0;
   1743 
   1744     count =
   1745         xmlOutputBufferWriteBinHex(writer->out, len,
   1746                                    (unsigned char *) data + start);
   1747     if (count < 0)
   1748         return -1;
   1749     sum += count;
   1750 
   1751     return sum;
   1752 }
   1753 
   1754 /**
   1755  * xmlTextWriterStartAttribute:
   1756  * @writer:  the xmlTextWriterPtr
   1757  * @name:  element name
   1758  *
   1759  * Start an xml attribute.
   1760  *
   1761  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1762  */
   1763 int
   1764 xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
   1765 {
   1766     int count;
   1767     int sum;
   1768     xmlLinkPtr lk;
   1769     xmlTextWriterStackEntry *p;
   1770 
   1771     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
   1772         return -1;
   1773 
   1774     sum = 0;
   1775     lk = xmlListFront(writer->nodes);
   1776     if (lk == 0)
   1777         return -1;
   1778 
   1779     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1780     if (p == 0)
   1781         return -1;
   1782 
   1783     switch (p->state) {
   1784         case XML_TEXTWRITER_ATTRIBUTE:
   1785             count = xmlTextWriterEndAttribute(writer);
   1786             if (count < 0)
   1787                 return -1;
   1788             sum += count;
   1789             /* fallthrough */
   1790         case XML_TEXTWRITER_NAME:
   1791             count = xmlOutputBufferWriteString(writer->out, " ");
   1792             if (count < 0)
   1793                 return -1;
   1794             sum += count;
   1795             count =
   1796                 xmlOutputBufferWriteString(writer->out,
   1797                                            (const char *) name);
   1798             if (count < 0)
   1799                 return -1;
   1800             sum += count;
   1801             count = xmlOutputBufferWriteString(writer->out, "=");
   1802             if (count < 0)
   1803                 return -1;
   1804             sum += count;
   1805             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   1806             if (count < 0)
   1807                 return -1;
   1808             sum += count;
   1809             p->state = XML_TEXTWRITER_ATTRIBUTE;
   1810             break;
   1811         default:
   1812             return -1;
   1813     }
   1814 
   1815     return sum;
   1816 }
   1817 
   1818 /**
   1819  * xmlTextWriterStartAttributeNS:
   1820  * @writer:  the xmlTextWriterPtr
   1821  * @prefix:  namespace prefix or NULL
   1822  * @name:  element local name
   1823  * @namespaceURI:  namespace URI or NULL
   1824  *
   1825  * Start an xml attribute with namespace support.
   1826  *
   1827  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1828  */
   1829 int
   1830 xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
   1831                               const xmlChar * prefix, const xmlChar * name,
   1832                               const xmlChar * namespaceURI)
   1833 {
   1834     int count;
   1835     int sum;
   1836     xmlChar *buf;
   1837     xmlTextWriterNsStackEntry *p;
   1838 
   1839     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
   1840         return -1;
   1841 
   1842     /* Handle namespace first in case of error */
   1843     if (namespaceURI != 0) {
   1844         xmlTextWriterNsStackEntry nsentry, *curns;
   1845 
   1846         buf = xmlStrdup(BAD_CAST "xmlns");
   1847         if (prefix != 0) {
   1848             buf = xmlStrcat(buf, BAD_CAST ":");
   1849             buf = xmlStrcat(buf, prefix);
   1850         }
   1851 
   1852         nsentry.prefix = buf;
   1853         nsentry.uri = (xmlChar *)namespaceURI;
   1854         nsentry.elem = xmlListFront(writer->nodes);
   1855 
   1856         curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
   1857                                                            (void *)&nsentry);
   1858         if ((curns != NULL)) {
   1859             xmlFree(buf);
   1860             if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
   1861                 /* Namespace already defined on element skip */
   1862                 buf = NULL;
   1863             } else {
   1864                 /* Prefix mismatch so error out */
   1865                 return -1;
   1866             }
   1867         }
   1868 
   1869         /* Do not add namespace decl to list - it is already there */
   1870         if (buf != NULL) {
   1871             p = (xmlTextWriterNsStackEntry *)
   1872                 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
   1873             if (p == 0) {
   1874                 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   1875 								        "xmlTextWriterStartAttributeNS : out of memory!\n");
   1876                 return -1;
   1877             }
   1878 
   1879             p->prefix = buf;
   1880             p->uri = xmlStrdup(namespaceURI);
   1881             if (p->uri == 0) {
   1882                 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   1883                         "xmlTextWriterStartAttributeNS : out of memory!\n");
   1884                 xmlFree(p);
   1885                 return -1;
   1886             }
   1887             p->elem = xmlListFront(writer->nodes);
   1888 
   1889             xmlListPushFront(writer->nsstack, p);
   1890         }
   1891     }
   1892 
   1893     buf = NULL;
   1894     if (prefix != 0) {
   1895         buf = xmlStrdup(prefix);
   1896         buf = xmlStrcat(buf, BAD_CAST ":");
   1897     }
   1898     buf = xmlStrcat(buf, name);
   1899 
   1900     sum = 0;
   1901     count = xmlTextWriterStartAttribute(writer, buf);
   1902     xmlFree(buf);
   1903     if (count < 0)
   1904         return -1;
   1905     sum += count;
   1906 
   1907     return sum;
   1908 }
   1909 
   1910 /**
   1911  * xmlTextWriterEndAttribute:
   1912  * @writer:  the xmlTextWriterPtr
   1913  *
   1914  * End the current xml element.
   1915  *
   1916  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1917  */
   1918 int
   1919 xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
   1920 {
   1921     int count;
   1922     int sum;
   1923     xmlLinkPtr lk;
   1924     xmlTextWriterStackEntry *p;
   1925 
   1926     if (writer == NULL)
   1927         return -1;
   1928 
   1929     lk = xmlListFront(writer->nodes);
   1930     if (lk == 0) {
   1931         return -1;
   1932     }
   1933 
   1934     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   1935     if (p == 0) {
   1936         return -1;
   1937     }
   1938 
   1939     sum = 0;
   1940     switch (p->state) {
   1941         case XML_TEXTWRITER_ATTRIBUTE:
   1942             p->state = XML_TEXTWRITER_NAME;
   1943 
   1944             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   1945             if (count < 0) {
   1946                 return -1;
   1947             }
   1948             sum += count;
   1949             break;
   1950         default:
   1951             return -1;
   1952     }
   1953 
   1954     return sum;
   1955 }
   1956 
   1957 /**
   1958  * xmlTextWriterWriteFormatAttribute:
   1959  * @writer:  the xmlTextWriterPtr
   1960  * @name:  attribute name
   1961  * @format:  format string (see printf)
   1962  * @...:  extra parameters for the format
   1963  *
   1964  * Write a formatted xml attribute.
   1965  *
   1966  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1967  */
   1968 int XMLCDECL
   1969 xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
   1970                                   const xmlChar * name, const char *format,
   1971                                   ...)
   1972 {
   1973     int rc;
   1974     va_list ap;
   1975 
   1976     va_start(ap, format);
   1977 
   1978     rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
   1979 
   1980     va_end(ap);
   1981     return rc;
   1982 }
   1983 
   1984 /**
   1985  * xmlTextWriterWriteVFormatAttribute:
   1986  * @writer:  the xmlTextWriterPtr
   1987  * @name:  attribute name
   1988  * @format:  format string (see printf)
   1989  * @argptr:  pointer to the first member of the variable argument list.
   1990  *
   1991  * Write a formatted xml attribute.
   1992  *
   1993  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   1994  */
   1995 int
   1996 xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
   1997                                    const xmlChar * name,
   1998                                    const char *format, va_list argptr)
   1999 {
   2000     int rc;
   2001     xmlChar *buf;
   2002 
   2003     if (writer == NULL)
   2004         return -1;
   2005 
   2006     buf = xmlTextWriterVSprintf(format, argptr);
   2007     if (buf == NULL)
   2008         return -1;
   2009 
   2010     rc = xmlTextWriterWriteAttribute(writer, name, buf);
   2011 
   2012     xmlFree(buf);
   2013     return rc;
   2014 }
   2015 
   2016 /**
   2017  * xmlTextWriterWriteAttribute:
   2018  * @writer:  the xmlTextWriterPtr
   2019  * @name:  attribute name
   2020  * @content:  attribute content
   2021  *
   2022  * Write an xml attribute.
   2023  *
   2024  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2025  */
   2026 int
   2027 xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
   2028                             const xmlChar * content)
   2029 {
   2030     int count;
   2031     int sum;
   2032 
   2033     sum = 0;
   2034     count = xmlTextWriterStartAttribute(writer, name);
   2035     if (count < 0)
   2036         return -1;
   2037     sum += count;
   2038     count = xmlTextWriterWriteString(writer, content);
   2039     if (count < 0)
   2040         return -1;
   2041     sum += count;
   2042     count = xmlTextWriterEndAttribute(writer);
   2043     if (count < 0)
   2044         return -1;
   2045     sum += count;
   2046 
   2047     return sum;
   2048 }
   2049 
   2050 /**
   2051  * xmlTextWriterWriteFormatAttributeNS:
   2052  * @writer:  the xmlTextWriterPtr
   2053  * @prefix:  namespace prefix
   2054  * @name:  attribute local name
   2055  * @namespaceURI:  namespace URI
   2056  * @format:  format string (see printf)
   2057  * @...:  extra parameters for the format
   2058  *
   2059  * Write a formatted xml attribute.with namespace support
   2060  *
   2061  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2062  */
   2063 int XMLCDECL
   2064 xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
   2065                                     const xmlChar * prefix,
   2066                                     const xmlChar * name,
   2067                                     const xmlChar * namespaceURI,
   2068                                     const char *format, ...)
   2069 {
   2070     int rc;
   2071     va_list ap;
   2072 
   2073     va_start(ap, format);
   2074 
   2075     rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
   2076                                               namespaceURI, format, ap);
   2077 
   2078     va_end(ap);
   2079     return rc;
   2080 }
   2081 
   2082 /**
   2083  * xmlTextWriterWriteVFormatAttributeNS:
   2084  * @writer:  the xmlTextWriterPtr
   2085  * @prefix:  namespace prefix
   2086  * @name:  attribute local name
   2087  * @namespaceURI:  namespace URI
   2088  * @format:  format string (see printf)
   2089  * @argptr:  pointer to the first member of the variable argument list.
   2090  *
   2091  * Write a formatted xml attribute.with namespace support
   2092  *
   2093  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2094  */
   2095 int
   2096 xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
   2097                                      const xmlChar * prefix,
   2098                                      const xmlChar * name,
   2099                                      const xmlChar * namespaceURI,
   2100                                      const char *format, va_list argptr)
   2101 {
   2102     int rc;
   2103     xmlChar *buf;
   2104 
   2105     if (writer == NULL)
   2106         return -1;
   2107 
   2108     buf = xmlTextWriterVSprintf(format, argptr);
   2109     if (buf == NULL)
   2110         return -1;
   2111 
   2112     rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
   2113                                        buf);
   2114 
   2115     xmlFree(buf);
   2116     return rc;
   2117 }
   2118 
   2119 /**
   2120  * xmlTextWriterWriteAttributeNS:
   2121  * @writer:  the xmlTextWriterPtr
   2122  * @prefix:  namespace prefix
   2123  * @name:  attribute local name
   2124  * @namespaceURI:  namespace URI
   2125  * @content:  attribute content
   2126  *
   2127  * Write an xml attribute.
   2128  *
   2129  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2130  */
   2131 int
   2132 xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
   2133                               const xmlChar * prefix, const xmlChar * name,
   2134                               const xmlChar * namespaceURI,
   2135                               const xmlChar * content)
   2136 {
   2137     int count;
   2138     int sum;
   2139 
   2140     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
   2141         return -1;
   2142 
   2143     sum = 0;
   2144     count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
   2145     if (count < 0)
   2146         return -1;
   2147     sum += count;
   2148     count = xmlTextWriterWriteString(writer, content);
   2149     if (count < 0)
   2150         return -1;
   2151     sum += count;
   2152     count = xmlTextWriterEndAttribute(writer);
   2153     if (count < 0)
   2154         return -1;
   2155     sum += count;
   2156 
   2157     return sum;
   2158 }
   2159 
   2160 /**
   2161  * xmlTextWriterWriteFormatElement:
   2162  * @writer:  the xmlTextWriterPtr
   2163  * @name:  element name
   2164  * @format:  format string (see printf)
   2165  * @...:  extra parameters for the format
   2166  *
   2167  * Write a formatted xml element.
   2168  *
   2169  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2170  */
   2171 int XMLCDECL
   2172 xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
   2173                                 const xmlChar * name, const char *format,
   2174                                 ...)
   2175 {
   2176     int rc;
   2177     va_list ap;
   2178 
   2179     va_start(ap, format);
   2180 
   2181     rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
   2182 
   2183     va_end(ap);
   2184     return rc;
   2185 }
   2186 
   2187 /**
   2188  * xmlTextWriterWriteVFormatElement:
   2189  * @writer:  the xmlTextWriterPtr
   2190  * @name:  element name
   2191  * @format:  format string (see printf)
   2192  * @argptr:  pointer to the first member of the variable argument list.
   2193  *
   2194  * Write a formatted xml element.
   2195  *
   2196  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2197  */
   2198 int
   2199 xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
   2200                                  const xmlChar * name, const char *format,
   2201                                  va_list argptr)
   2202 {
   2203     int rc;
   2204     xmlChar *buf;
   2205 
   2206     if (writer == NULL)
   2207         return -1;
   2208 
   2209     buf = xmlTextWriterVSprintf(format, argptr);
   2210     if (buf == NULL)
   2211         return -1;
   2212 
   2213     rc = xmlTextWriterWriteElement(writer, name, buf);
   2214 
   2215     xmlFree(buf);
   2216     return rc;
   2217 }
   2218 
   2219 /**
   2220  * xmlTextWriterWriteElement:
   2221  * @writer:  the xmlTextWriterPtr
   2222  * @name:  element name
   2223  * @content:  element content
   2224  *
   2225  * Write an xml element.
   2226  *
   2227  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2228  */
   2229 int
   2230 xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
   2231                           const xmlChar * content)
   2232 {
   2233     int count;
   2234     int sum;
   2235 
   2236     sum = 0;
   2237     count = xmlTextWriterStartElement(writer, name);
   2238     if (count == -1)
   2239         return -1;
   2240     sum += count;
   2241     count = xmlTextWriterWriteString(writer, content);
   2242     if (count == -1)
   2243         return -1;
   2244     sum += count;
   2245     count = xmlTextWriterEndElement(writer);
   2246     if (count == -1)
   2247         return -1;
   2248     sum += count;
   2249 
   2250     return sum;
   2251 }
   2252 
   2253 /**
   2254  * xmlTextWriterWriteFormatElementNS:
   2255  * @writer:  the xmlTextWriterPtr
   2256  * @prefix:  namespace prefix
   2257  * @name:  element local name
   2258  * @namespaceURI:  namespace URI
   2259  * @format:  format string (see printf)
   2260  * @...:  extra parameters for the format
   2261  *
   2262  * Write a formatted xml element with namespace support.
   2263  *
   2264  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2265  */
   2266 int XMLCDECL
   2267 xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
   2268                                   const xmlChar * prefix,
   2269                                   const xmlChar * name,
   2270                                   const xmlChar * namespaceURI,
   2271                                   const char *format, ...)
   2272 {
   2273     int rc;
   2274     va_list ap;
   2275 
   2276     va_start(ap, format);
   2277 
   2278     rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
   2279                                             namespaceURI, format, ap);
   2280 
   2281     va_end(ap);
   2282     return rc;
   2283 }
   2284 
   2285 /**
   2286  * xmlTextWriterWriteVFormatElementNS:
   2287  * @writer:  the xmlTextWriterPtr
   2288  * @prefix:  namespace prefix
   2289  * @name:  element local name
   2290  * @namespaceURI:  namespace URI
   2291  * @format:  format string (see printf)
   2292  * @argptr:  pointer to the first member of the variable argument list.
   2293  *
   2294  * Write a formatted xml element with namespace support.
   2295  *
   2296  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2297  */
   2298 int
   2299 xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
   2300                                    const xmlChar * prefix,
   2301                                    const xmlChar * name,
   2302                                    const xmlChar * namespaceURI,
   2303                                    const char *format, va_list argptr)
   2304 {
   2305     int rc;
   2306     xmlChar *buf;
   2307 
   2308     if (writer == NULL)
   2309         return -1;
   2310 
   2311     buf = xmlTextWriterVSprintf(format, argptr);
   2312     if (buf == NULL)
   2313         return -1;
   2314 
   2315     rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
   2316                                      buf);
   2317 
   2318     xmlFree(buf);
   2319     return rc;
   2320 }
   2321 
   2322 /**
   2323  * xmlTextWriterWriteElementNS:
   2324  * @writer:  the xmlTextWriterPtr
   2325  * @prefix:  namespace prefix
   2326  * @name:  element local name
   2327  * @namespaceURI:  namespace URI
   2328  * @content:  element content
   2329  *
   2330  * Write an xml element with namespace support.
   2331  *
   2332  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2333  */
   2334 int
   2335 xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
   2336                             const xmlChar * prefix, const xmlChar * name,
   2337                             const xmlChar * namespaceURI,
   2338                             const xmlChar * content)
   2339 {
   2340     int count;
   2341     int sum;
   2342 
   2343     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
   2344         return -1;
   2345 
   2346     sum = 0;
   2347     count =
   2348         xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
   2349     if (count < 0)
   2350         return -1;
   2351     sum += count;
   2352     count = xmlTextWriterWriteString(writer, content);
   2353     if (count == -1)
   2354         return -1;
   2355     sum += count;
   2356     count = xmlTextWriterEndElement(writer);
   2357     if (count == -1)
   2358         return -1;
   2359     sum += count;
   2360 
   2361     return sum;
   2362 }
   2363 
   2364 /**
   2365  * xmlTextWriterStartPI:
   2366  * @writer:  the xmlTextWriterPtr
   2367  * @target:  PI target
   2368  *
   2369  * Start an xml PI.
   2370  *
   2371  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2372  */
   2373 int
   2374 xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
   2375 {
   2376     int count;
   2377     int sum;
   2378     xmlLinkPtr lk;
   2379     xmlTextWriterStackEntry *p;
   2380 
   2381     if ((writer == NULL) || (target == NULL) || (*target == '\0'))
   2382         return -1;
   2383 
   2384     if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
   2385         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   2386                         "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
   2387         return -1;
   2388     }
   2389 
   2390     sum = 0;
   2391     lk = xmlListFront(writer->nodes);
   2392     if (lk != 0) {
   2393         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   2394         if (p != 0) {
   2395             switch (p->state) {
   2396                 case XML_TEXTWRITER_ATTRIBUTE:
   2397                     count = xmlTextWriterEndAttribute(writer);
   2398                     if (count < 0)
   2399                         return -1;
   2400                     sum += count;
   2401                     /* fallthrough */
   2402                 case XML_TEXTWRITER_NAME:
   2403                     /* Output namespace declarations */
   2404                     count = xmlTextWriterOutputNSDecl(writer);
   2405                     if (count < 0)
   2406                         return -1;
   2407                     sum += count;
   2408                     count = xmlOutputBufferWriteString(writer->out, ">");
   2409                     if (count < 0)
   2410                         return -1;
   2411                     sum += count;
   2412                     p->state = XML_TEXTWRITER_TEXT;
   2413                     break;
   2414                 case XML_TEXTWRITER_NONE:
   2415                 case XML_TEXTWRITER_TEXT:
   2416                 case XML_TEXTWRITER_DTD:
   2417                     break;
   2418                 case XML_TEXTWRITER_PI:
   2419                 case XML_TEXTWRITER_PI_TEXT:
   2420                     xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   2421                                     "xmlTextWriterStartPI : nested PI!\n");
   2422                     return -1;
   2423                 default:
   2424                     return -1;
   2425             }
   2426         }
   2427     }
   2428 
   2429     p = (xmlTextWriterStackEntry *)
   2430         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   2431     if (p == 0) {
   2432         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   2433                         "xmlTextWriterStartPI : out of memory!\n");
   2434         return -1;
   2435     }
   2436 
   2437     p->name = xmlStrdup(target);
   2438     if (p->name == 0) {
   2439         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   2440                         "xmlTextWriterStartPI : out of memory!\n");
   2441         xmlFree(p);
   2442         return -1;
   2443     }
   2444     p->state = XML_TEXTWRITER_PI;
   2445 
   2446     xmlListPushFront(writer->nodes, p);
   2447 
   2448     count = xmlOutputBufferWriteString(writer->out, "<?");
   2449     if (count < 0)
   2450         return -1;
   2451     sum += count;
   2452     count =
   2453         xmlOutputBufferWriteString(writer->out, (const char *) p->name);
   2454     if (count < 0)
   2455         return -1;
   2456     sum += count;
   2457 
   2458     return sum;
   2459 }
   2460 
   2461 /**
   2462  * xmlTextWriterEndPI:
   2463  * @writer:  the xmlTextWriterPtr
   2464  *
   2465  * End the current xml PI.
   2466  *
   2467  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2468  */
   2469 int
   2470 xmlTextWriterEndPI(xmlTextWriterPtr writer)
   2471 {
   2472     int count;
   2473     int sum;
   2474     xmlLinkPtr lk;
   2475     xmlTextWriterStackEntry *p;
   2476 
   2477     if (writer == NULL)
   2478         return -1;
   2479 
   2480     lk = xmlListFront(writer->nodes);
   2481     if (lk == 0)
   2482         return 0;
   2483 
   2484     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   2485     if (p == 0)
   2486         return 0;
   2487 
   2488     sum = 0;
   2489     switch (p->state) {
   2490         case XML_TEXTWRITER_PI:
   2491         case XML_TEXTWRITER_PI_TEXT:
   2492             count = xmlOutputBufferWriteString(writer->out, "?>");
   2493             if (count < 0)
   2494                 return -1;
   2495             sum += count;
   2496             break;
   2497         default:
   2498             return -1;
   2499     }
   2500 
   2501     if (writer->indent) {
   2502         count = xmlOutputBufferWriteString(writer->out, "\n");
   2503 	if (count < 0)
   2504 	return -1;
   2505         sum += count;
   2506     }
   2507 
   2508     xmlListPopFront(writer->nodes);
   2509     return sum;
   2510 }
   2511 
   2512 /**
   2513  * xmlTextWriterWriteFormatPI:
   2514  * @writer:  the xmlTextWriterPtr
   2515  * @target:  PI target
   2516  * @format:  format string (see printf)
   2517  * @...:  extra parameters for the format
   2518  *
   2519  * Write a formatted PI.
   2520  *
   2521  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2522  */
   2523 int XMLCDECL
   2524 xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
   2525                            const char *format, ...)
   2526 {
   2527     int rc;
   2528     va_list ap;
   2529 
   2530     va_start(ap, format);
   2531 
   2532     rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
   2533 
   2534     va_end(ap);
   2535     return rc;
   2536 }
   2537 
   2538 /**
   2539  * xmlTextWriterWriteVFormatPI:
   2540  * @writer:  the xmlTextWriterPtr
   2541  * @target:  PI target
   2542  * @format:  format string (see printf)
   2543  * @argptr:  pointer to the first member of the variable argument list.
   2544  *
   2545  * Write a formatted xml PI.
   2546  *
   2547  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2548  */
   2549 int
   2550 xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
   2551                             const xmlChar * target, const char *format,
   2552                             va_list argptr)
   2553 {
   2554     int rc;
   2555     xmlChar *buf;
   2556 
   2557     if (writer == NULL)
   2558         return -1;
   2559 
   2560     buf = xmlTextWriterVSprintf(format, argptr);
   2561     if (buf == NULL)
   2562         return -1;
   2563 
   2564     rc = xmlTextWriterWritePI(writer, target, buf);
   2565 
   2566     xmlFree(buf);
   2567     return rc;
   2568 }
   2569 
   2570 /**
   2571  * xmlTextWriterWritePI:
   2572  * @writer:  the xmlTextWriterPtr
   2573  * @target:  PI target
   2574  * @content:  PI content
   2575  *
   2576  * Write an xml PI.
   2577  *
   2578  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2579  */
   2580 int
   2581 xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
   2582                      const xmlChar * content)
   2583 {
   2584     int count;
   2585     int sum;
   2586 
   2587     sum = 0;
   2588     count = xmlTextWriterStartPI(writer, target);
   2589     if (count == -1)
   2590         return -1;
   2591     sum += count;
   2592     if (content != 0) {
   2593         count = xmlTextWriterWriteString(writer, content);
   2594         if (count == -1)
   2595             return -1;
   2596         sum += count;
   2597     }
   2598     count = xmlTextWriterEndPI(writer);
   2599     if (count == -1)
   2600         return -1;
   2601     sum += count;
   2602 
   2603     return sum;
   2604 }
   2605 
   2606 /**
   2607  * xmlTextWriterStartCDATA:
   2608  * @writer:  the xmlTextWriterPtr
   2609  *
   2610  * Start an xml CDATA section.
   2611  *
   2612  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2613  */
   2614 int
   2615 xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
   2616 {
   2617     int count;
   2618     int sum;
   2619     xmlLinkPtr lk;
   2620     xmlTextWriterStackEntry *p;
   2621 
   2622     if (writer == NULL)
   2623         return -1;
   2624 
   2625     sum = 0;
   2626     lk = xmlListFront(writer->nodes);
   2627     if (lk != 0) {
   2628         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   2629         if (p != 0) {
   2630             switch (p->state) {
   2631                 case XML_TEXTWRITER_NONE:
   2632 		case XML_TEXTWRITER_TEXT:
   2633                 case XML_TEXTWRITER_PI:
   2634                 case XML_TEXTWRITER_PI_TEXT:
   2635                     break;
   2636                 case XML_TEXTWRITER_ATTRIBUTE:
   2637                     count = xmlTextWriterEndAttribute(writer);
   2638                     if (count < 0)
   2639                         return -1;
   2640                     sum += count;
   2641                     /* fallthrough */
   2642                 case XML_TEXTWRITER_NAME:
   2643                     /* Output namespace declarations */
   2644                     count = xmlTextWriterOutputNSDecl(writer);
   2645                     if (count < 0)
   2646                         return -1;
   2647                     sum += count;
   2648                     count = xmlOutputBufferWriteString(writer->out, ">");
   2649                     if (count < 0)
   2650                         return -1;
   2651                     sum += count;
   2652                     p->state = XML_TEXTWRITER_TEXT;
   2653                     break;
   2654                 case XML_TEXTWRITER_CDATA:
   2655                     xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   2656                                     "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
   2657                     return -1;
   2658                 default:
   2659                     return -1;
   2660             }
   2661         }
   2662     }
   2663 
   2664     p = (xmlTextWriterStackEntry *)
   2665         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   2666     if (p == 0) {
   2667         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   2668                         "xmlTextWriterStartCDATA : out of memory!\n");
   2669         return -1;
   2670     }
   2671 
   2672     p->name = NULL;
   2673     p->state = XML_TEXTWRITER_CDATA;
   2674 
   2675     xmlListPushFront(writer->nodes, p);
   2676 
   2677     count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
   2678     if (count < 0)
   2679         return -1;
   2680     sum += count;
   2681 
   2682     return sum;
   2683 }
   2684 
   2685 /**
   2686  * xmlTextWriterEndCDATA:
   2687  * @writer:  the xmlTextWriterPtr
   2688  *
   2689  * End an xml CDATA section.
   2690  *
   2691  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2692  */
   2693 int
   2694 xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
   2695 {
   2696     int count;
   2697     int sum;
   2698     xmlLinkPtr lk;
   2699     xmlTextWriterStackEntry *p;
   2700 
   2701     if (writer == NULL)
   2702         return -1;
   2703 
   2704     lk = xmlListFront(writer->nodes);
   2705     if (lk == 0)
   2706         return -1;
   2707 
   2708     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   2709     if (p == 0)
   2710         return -1;
   2711 
   2712     sum = 0;
   2713     switch (p->state) {
   2714         case XML_TEXTWRITER_CDATA:
   2715             count = xmlOutputBufferWriteString(writer->out, "]]>");
   2716             if (count < 0)
   2717                 return -1;
   2718             sum += count;
   2719             break;
   2720         default:
   2721             return -1;
   2722     }
   2723 
   2724     xmlListPopFront(writer->nodes);
   2725     return sum;
   2726 }
   2727 
   2728 /**
   2729  * xmlTextWriterWriteFormatCDATA:
   2730  * @writer:  the xmlTextWriterPtr
   2731  * @format:  format string (see printf)
   2732  * @...:  extra parameters for the format
   2733  *
   2734  * Write a formatted xml CDATA.
   2735  *
   2736  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2737  */
   2738 int XMLCDECL
   2739 xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
   2740                               ...)
   2741 {
   2742     int rc;
   2743     va_list ap;
   2744 
   2745     va_start(ap, format);
   2746 
   2747     rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
   2748 
   2749     va_end(ap);
   2750     return rc;
   2751 }
   2752 
   2753 /**
   2754  * xmlTextWriterWriteVFormatCDATA:
   2755  * @writer:  the xmlTextWriterPtr
   2756  * @format:  format string (see printf)
   2757  * @argptr:  pointer to the first member of the variable argument list.
   2758  *
   2759  * Write a formatted xml CDATA.
   2760  *
   2761  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2762  */
   2763 int
   2764 xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
   2765                                va_list argptr)
   2766 {
   2767     int rc;
   2768     xmlChar *buf;
   2769 
   2770     if (writer == NULL)
   2771         return -1;
   2772 
   2773     buf = xmlTextWriterVSprintf(format, argptr);
   2774     if (buf == NULL)
   2775         return -1;
   2776 
   2777     rc = xmlTextWriterWriteCDATA(writer, buf);
   2778 
   2779     xmlFree(buf);
   2780     return rc;
   2781 }
   2782 
   2783 /**
   2784  * xmlTextWriterWriteCDATA:
   2785  * @writer:  the xmlTextWriterPtr
   2786  * @content:  CDATA content
   2787  *
   2788  * Write an xml CDATA.
   2789  *
   2790  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2791  */
   2792 int
   2793 xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
   2794 {
   2795     int count;
   2796     int sum;
   2797 
   2798     sum = 0;
   2799     count = xmlTextWriterStartCDATA(writer);
   2800     if (count == -1)
   2801         return -1;
   2802     sum += count;
   2803     if (content != 0) {
   2804         count = xmlTextWriterWriteString(writer, content);
   2805         if (count == -1)
   2806             return -1;
   2807         sum += count;
   2808     }
   2809     count = xmlTextWriterEndCDATA(writer);
   2810     if (count == -1)
   2811         return -1;
   2812     sum += count;
   2813 
   2814     return sum;
   2815 }
   2816 
   2817 /**
   2818  * xmlTextWriterStartDTD:
   2819  * @writer:  the xmlTextWriterPtr
   2820  * @name:  the name of the DTD
   2821  * @pubid:  the public identifier, which is an alternative to the system identifier
   2822  * @sysid:  the system identifier, which is the URI of the DTD
   2823  *
   2824  * Start an xml DTD.
   2825  *
   2826  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2827  */
   2828 int
   2829 xmlTextWriterStartDTD(xmlTextWriterPtr writer,
   2830                       const xmlChar * name,
   2831                       const xmlChar * pubid, const xmlChar * sysid)
   2832 {
   2833     int count;
   2834     int sum;
   2835     xmlLinkPtr lk;
   2836     xmlTextWriterStackEntry *p;
   2837 
   2838     if (writer == NULL || name == NULL || *name == '\0')
   2839         return -1;
   2840 
   2841     sum = 0;
   2842     lk = xmlListFront(writer->nodes);
   2843     if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
   2844         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   2845                         "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
   2846         return -1;
   2847     }
   2848 
   2849     p = (xmlTextWriterStackEntry *)
   2850         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   2851     if (p == 0) {
   2852         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   2853                         "xmlTextWriterStartDTD : out of memory!\n");
   2854         return -1;
   2855     }
   2856 
   2857     p->name = xmlStrdup(name);
   2858     if (p->name == 0) {
   2859         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   2860                         "xmlTextWriterStartDTD : out of memory!\n");
   2861         xmlFree(p);
   2862         return -1;
   2863     }
   2864     p->state = XML_TEXTWRITER_DTD;
   2865 
   2866     xmlListPushFront(writer->nodes, p);
   2867 
   2868     count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
   2869     if (count < 0)
   2870         return -1;
   2871     sum += count;
   2872     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
   2873     if (count < 0)
   2874         return -1;
   2875     sum += count;
   2876 
   2877     if (pubid != 0) {
   2878         if (sysid == 0) {
   2879             xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   2880                             "xmlTextWriterStartDTD : system identifier needed!\n");
   2881             return -1;
   2882         }
   2883 
   2884         if (writer->indent)
   2885             count = xmlOutputBufferWrite(writer->out, 1, "\n");
   2886         else
   2887             count = xmlOutputBufferWrite(writer->out, 1, " ");
   2888         if (count < 0)
   2889             return -1;
   2890         sum += count;
   2891 
   2892         count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
   2893         if (count < 0)
   2894             return -1;
   2895         sum += count;
   2896 
   2897         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   2898         if (count < 0)
   2899             return -1;
   2900         sum += count;
   2901 
   2902         count =
   2903             xmlOutputBufferWriteString(writer->out, (const char *) pubid);
   2904         if (count < 0)
   2905             return -1;
   2906         sum += count;
   2907 
   2908         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   2909         if (count < 0)
   2910             return -1;
   2911         sum += count;
   2912     }
   2913 
   2914     if (sysid != 0) {
   2915         if (pubid == 0) {
   2916             if (writer->indent)
   2917                 count = xmlOutputBufferWrite(writer->out, 1, "\n");
   2918             else
   2919                 count = xmlOutputBufferWrite(writer->out, 1, " ");
   2920             if (count < 0)
   2921                 return -1;
   2922             sum += count;
   2923             count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
   2924             if (count < 0)
   2925                 return -1;
   2926             sum += count;
   2927         } else {
   2928 			if (writer->indent)
   2929             count = xmlOutputBufferWriteString(writer->out, "\n       ");
   2930             else
   2931                 count = xmlOutputBufferWrite(writer->out, 1, " ");
   2932             if (count < 0)
   2933                 return -1;
   2934             sum += count;
   2935         }
   2936 
   2937         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   2938         if (count < 0)
   2939             return -1;
   2940         sum += count;
   2941 
   2942         count =
   2943             xmlOutputBufferWriteString(writer->out, (const char *) sysid);
   2944         if (count < 0)
   2945             return -1;
   2946         sum += count;
   2947 
   2948         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   2949         if (count < 0)
   2950             return -1;
   2951         sum += count;
   2952     }
   2953 
   2954     return sum;
   2955 }
   2956 
   2957 /**
   2958  * xmlTextWriterEndDTD:
   2959  * @writer:  the xmlTextWriterPtr
   2960  *
   2961  * End an xml DTD.
   2962  *
   2963  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   2964  */
   2965 int
   2966 xmlTextWriterEndDTD(xmlTextWriterPtr writer)
   2967 {
   2968     int loop;
   2969     int count;
   2970     int sum;
   2971     xmlLinkPtr lk;
   2972     xmlTextWriterStackEntry *p;
   2973 
   2974     if (writer == NULL)
   2975         return -1;
   2976 
   2977     sum = 0;
   2978     loop = 1;
   2979     while (loop) {
   2980         lk = xmlListFront(writer->nodes);
   2981         if (lk == NULL)
   2982             break;
   2983         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   2984         if (p == 0)
   2985             break;
   2986         switch (p->state) {
   2987             case XML_TEXTWRITER_DTD_TEXT:
   2988                 count = xmlOutputBufferWriteString(writer->out, "]");
   2989                 if (count < 0)
   2990                     return -1;
   2991                 sum += count;
   2992                 /* fallthrough */
   2993             case XML_TEXTWRITER_DTD:
   2994                 count = xmlOutputBufferWriteString(writer->out, ">");
   2995 
   2996                 if (writer->indent) {
   2997                     if (count < 0)
   2998                         return -1;
   2999                     sum += count;
   3000                     count = xmlOutputBufferWriteString(writer->out, "\n");
   3001                 }
   3002 
   3003                 xmlListPopFront(writer->nodes);
   3004                 break;
   3005             case XML_TEXTWRITER_DTD_ELEM:
   3006             case XML_TEXTWRITER_DTD_ELEM_TEXT:
   3007                 count = xmlTextWriterEndDTDElement(writer);
   3008                 break;
   3009             case XML_TEXTWRITER_DTD_ATTL:
   3010             case XML_TEXTWRITER_DTD_ATTL_TEXT:
   3011                 count = xmlTextWriterEndDTDAttlist(writer);
   3012                 break;
   3013             case XML_TEXTWRITER_DTD_ENTY:
   3014             case XML_TEXTWRITER_DTD_PENT:
   3015             case XML_TEXTWRITER_DTD_ENTY_TEXT:
   3016                 count = xmlTextWriterEndDTDEntity(writer);
   3017                 break;
   3018             case XML_TEXTWRITER_COMMENT:
   3019                 count = xmlTextWriterEndComment(writer);
   3020                 break;
   3021             default:
   3022                 loop = 0;
   3023                 continue;
   3024         }
   3025 
   3026         if (count < 0)
   3027             return -1;
   3028         sum += count;
   3029     }
   3030 
   3031     return sum;
   3032 }
   3033 
   3034 /**
   3035  * xmlTextWriterWriteFormatDTD:
   3036  * @writer:  the xmlTextWriterPtr
   3037  * @name:  the name of the DTD
   3038  * @pubid:  the public identifier, which is an alternative to the system identifier
   3039  * @sysid:  the system identifier, which is the URI of the DTD
   3040  * @format:  format string (see printf)
   3041  * @...:  extra parameters for the format
   3042  *
   3043  * Write a DTD with a formatted markup declarations part.
   3044  *
   3045  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3046  */
   3047 int XMLCDECL
   3048 xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
   3049                             const xmlChar * name,
   3050                             const xmlChar * pubid,
   3051                             const xmlChar * sysid, const char *format, ...)
   3052 {
   3053     int rc;
   3054     va_list ap;
   3055 
   3056     va_start(ap, format);
   3057 
   3058     rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
   3059                                       ap);
   3060 
   3061     va_end(ap);
   3062     return rc;
   3063 }
   3064 
   3065 /**
   3066  * xmlTextWriterWriteVFormatDTD:
   3067  * @writer:  the xmlTextWriterPtr
   3068  * @name:  the name of the DTD
   3069  * @pubid:  the public identifier, which is an alternative to the system identifier
   3070  * @sysid:  the system identifier, which is the URI of the DTD
   3071  * @format:  format string (see printf)
   3072  * @argptr:  pointer to the first member of the variable argument list.
   3073  *
   3074  * Write a DTD with a formatted markup declarations part.
   3075  *
   3076  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3077  */
   3078 int
   3079 xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
   3080                              const xmlChar * name,
   3081                              const xmlChar * pubid,
   3082                              const xmlChar * sysid,
   3083                              const char *format, va_list argptr)
   3084 {
   3085     int rc;
   3086     xmlChar *buf;
   3087 
   3088     if (writer == NULL)
   3089         return -1;
   3090 
   3091     buf = xmlTextWriterVSprintf(format, argptr);
   3092     if (buf == NULL)
   3093         return -1;
   3094 
   3095     rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
   3096 
   3097     xmlFree(buf);
   3098     return rc;
   3099 }
   3100 
   3101 /**
   3102  * xmlTextWriterWriteDTD:
   3103  * @writer:  the xmlTextWriterPtr
   3104  * @name:  the name of the DTD
   3105  * @pubid:  the public identifier, which is an alternative to the system identifier
   3106  * @sysid:  the system identifier, which is the URI of the DTD
   3107  * @subset:  string content of the DTD
   3108  *
   3109  * Write a DTD.
   3110  *
   3111  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3112  */
   3113 int
   3114 xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
   3115                       const xmlChar * name,
   3116                       const xmlChar * pubid,
   3117                       const xmlChar * sysid, const xmlChar * subset)
   3118 {
   3119     int count;
   3120     int sum;
   3121 
   3122     sum = 0;
   3123     count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
   3124     if (count == -1)
   3125         return -1;
   3126     sum += count;
   3127     if (subset != 0) {
   3128         count = xmlTextWriterWriteString(writer, subset);
   3129         if (count == -1)
   3130             return -1;
   3131         sum += count;
   3132     }
   3133     count = xmlTextWriterEndDTD(writer);
   3134     if (count == -1)
   3135         return -1;
   3136     sum += count;
   3137 
   3138     return sum;
   3139 }
   3140 
   3141 /**
   3142  * xmlTextWriterStartDTDElement:
   3143  * @writer:  the xmlTextWriterPtr
   3144  * @name:  the name of the DTD element
   3145  *
   3146  * Start an xml DTD element.
   3147  *
   3148  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3149  */
   3150 int
   3151 xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
   3152 {
   3153     int count;
   3154     int sum;
   3155     xmlLinkPtr lk;
   3156     xmlTextWriterStackEntry *p;
   3157 
   3158     if (writer == NULL || name == NULL || *name == '\0')
   3159         return -1;
   3160 
   3161     sum = 0;
   3162     lk = xmlListFront(writer->nodes);
   3163     if (lk == 0) {
   3164         return -1;
   3165     }
   3166 
   3167     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   3168     if (p != 0) {
   3169         switch (p->state) {
   3170             case XML_TEXTWRITER_DTD:
   3171                 count = xmlOutputBufferWriteString(writer->out, " [");
   3172                 if (count < 0)
   3173                     return -1;
   3174                 sum += count;
   3175                 if (writer->indent) {
   3176                     count = xmlOutputBufferWriteString(writer->out, "\n");
   3177                     if (count < 0)
   3178                         return -1;
   3179                     sum += count;
   3180                 }
   3181                 p->state = XML_TEXTWRITER_DTD_TEXT;
   3182                 /* fallthrough */
   3183             case XML_TEXTWRITER_DTD_TEXT:
   3184             case XML_TEXTWRITER_NONE:
   3185                 break;
   3186             default:
   3187                 return -1;
   3188         }
   3189     }
   3190 
   3191     p = (xmlTextWriterStackEntry *)
   3192         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   3193     if (p == 0) {
   3194         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   3195                         "xmlTextWriterStartDTDElement : out of memory!\n");
   3196         return -1;
   3197     }
   3198 
   3199     p->name = xmlStrdup(name);
   3200     if (p->name == 0) {
   3201         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   3202                         "xmlTextWriterStartDTDElement : out of memory!\n");
   3203         xmlFree(p);
   3204         return -1;
   3205     }
   3206     p->state = XML_TEXTWRITER_DTD_ELEM;
   3207 
   3208     xmlListPushFront(writer->nodes, p);
   3209 
   3210     if (writer->indent) {
   3211         count = xmlTextWriterWriteIndent(writer);
   3212         if (count < 0)
   3213             return -1;
   3214         sum += count;
   3215     }
   3216 
   3217     count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
   3218     if (count < 0)
   3219         return -1;
   3220     sum += count;
   3221     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
   3222     if (count < 0)
   3223         return -1;
   3224     sum += count;
   3225 
   3226     return sum;
   3227 }
   3228 
   3229 /**
   3230  * xmlTextWriterEndDTDElement:
   3231  * @writer:  the xmlTextWriterPtr
   3232  *
   3233  * End an xml DTD element.
   3234  *
   3235  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3236  */
   3237 int
   3238 xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
   3239 {
   3240     int count;
   3241     int sum;
   3242     xmlLinkPtr lk;
   3243     xmlTextWriterStackEntry *p;
   3244 
   3245     if (writer == NULL)
   3246         return -1;
   3247 
   3248     sum = 0;
   3249     lk = xmlListFront(writer->nodes);
   3250     if (lk == 0)
   3251         return -1;
   3252 
   3253     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   3254     if (p == 0)
   3255         return -1;
   3256 
   3257     switch (p->state) {
   3258         case XML_TEXTWRITER_DTD_ELEM:
   3259         case XML_TEXTWRITER_DTD_ELEM_TEXT:
   3260             count = xmlOutputBufferWriteString(writer->out, ">");
   3261             if (count < 0)
   3262                 return -1;
   3263             sum += count;
   3264             break;
   3265         default:
   3266             return -1;
   3267     }
   3268 
   3269     if (writer->indent) {
   3270         count = xmlOutputBufferWriteString(writer->out, "\n");
   3271         if (count < 0)
   3272             return -1;
   3273         sum += count;
   3274     }
   3275 
   3276     xmlListPopFront(writer->nodes);
   3277     return sum;
   3278 }
   3279 
   3280 /**
   3281  * xmlTextWriterWriteFormatDTDElement:
   3282  * @writer:  the xmlTextWriterPtr
   3283  * @name:  the name of the DTD element
   3284  * @format:  format string (see printf)
   3285  * @...:  extra parameters for the format
   3286  *
   3287  * Write a formatted DTD element.
   3288  *
   3289  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3290  */
   3291 int XMLCDECL
   3292 xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
   3293                                    const xmlChar * name,
   3294                                    const char *format, ...)
   3295 {
   3296     int rc;
   3297     va_list ap;
   3298 
   3299     va_start(ap, format);
   3300 
   3301     rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
   3302 
   3303     va_end(ap);
   3304     return rc;
   3305 }
   3306 
   3307 /**
   3308  * xmlTextWriterWriteVFormatDTDElement:
   3309  * @writer:  the xmlTextWriterPtr
   3310  * @name:  the name of the DTD element
   3311  * @format:  format string (see printf)
   3312  * @argptr:  pointer to the first member of the variable argument list.
   3313  *
   3314  * Write a formatted DTD element.
   3315  *
   3316  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3317  */
   3318 int
   3319 xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
   3320                                     const xmlChar * name,
   3321                                     const char *format, va_list argptr)
   3322 {
   3323     int rc;
   3324     xmlChar *buf;
   3325 
   3326     if (writer == NULL)
   3327         return -1;
   3328 
   3329     buf = xmlTextWriterVSprintf(format, argptr);
   3330     if (buf == NULL)
   3331         return -1;
   3332 
   3333     rc = xmlTextWriterWriteDTDElement(writer, name, buf);
   3334 
   3335     xmlFree(buf);
   3336     return rc;
   3337 }
   3338 
   3339 /**
   3340  * xmlTextWriterWriteDTDElement:
   3341  * @writer:  the xmlTextWriterPtr
   3342  * @name:  the name of the DTD element
   3343  * @content:  content of the element
   3344  *
   3345  * Write a DTD element.
   3346  *
   3347  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3348  */
   3349 int
   3350 xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
   3351                              const xmlChar * name, const xmlChar * content)
   3352 {
   3353     int count;
   3354     int sum;
   3355 
   3356     if (content == NULL)
   3357         return -1;
   3358 
   3359     sum = 0;
   3360     count = xmlTextWriterStartDTDElement(writer, name);
   3361     if (count == -1)
   3362         return -1;
   3363     sum += count;
   3364 
   3365     count = xmlTextWriterWriteString(writer, content);
   3366     if (count == -1)
   3367         return -1;
   3368     sum += count;
   3369 
   3370     count = xmlTextWriterEndDTDElement(writer);
   3371     if (count == -1)
   3372         return -1;
   3373     sum += count;
   3374 
   3375     return sum;
   3376 }
   3377 
   3378 /**
   3379  * xmlTextWriterStartDTDAttlist:
   3380  * @writer:  the xmlTextWriterPtr
   3381  * @name:  the name of the DTD ATTLIST
   3382  *
   3383  * Start an xml DTD ATTLIST.
   3384  *
   3385  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3386  */
   3387 int
   3388 xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
   3389 {
   3390     int count;
   3391     int sum;
   3392     xmlLinkPtr lk;
   3393     xmlTextWriterStackEntry *p;
   3394 
   3395     if (writer == NULL || name == NULL || *name == '\0')
   3396         return -1;
   3397 
   3398     sum = 0;
   3399     lk = xmlListFront(writer->nodes);
   3400     if (lk == 0) {
   3401         return -1;
   3402     }
   3403 
   3404     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   3405     if (p != 0) {
   3406         switch (p->state) {
   3407             case XML_TEXTWRITER_DTD:
   3408                 count = xmlOutputBufferWriteString(writer->out, " [");
   3409                 if (count < 0)
   3410                     return -1;
   3411                 sum += count;
   3412                 if (writer->indent) {
   3413                     count = xmlOutputBufferWriteString(writer->out, "\n");
   3414                     if (count < 0)
   3415                         return -1;
   3416                     sum += count;
   3417                 }
   3418                 p->state = XML_TEXTWRITER_DTD_TEXT;
   3419                 /* fallthrough */
   3420             case XML_TEXTWRITER_DTD_TEXT:
   3421             case XML_TEXTWRITER_NONE:
   3422                 break;
   3423             default:
   3424                 return -1;
   3425         }
   3426     }
   3427 
   3428     p = (xmlTextWriterStackEntry *)
   3429         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   3430     if (p == 0) {
   3431         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   3432                         "xmlTextWriterStartDTDAttlist : out of memory!\n");
   3433         return -1;
   3434     }
   3435 
   3436     p->name = xmlStrdup(name);
   3437     if (p->name == 0) {
   3438         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   3439                         "xmlTextWriterStartDTDAttlist : out of memory!\n");
   3440         xmlFree(p);
   3441         return -1;
   3442     }
   3443     p->state = XML_TEXTWRITER_DTD_ATTL;
   3444 
   3445     xmlListPushFront(writer->nodes, p);
   3446 
   3447     if (writer->indent) {
   3448         count = xmlTextWriterWriteIndent(writer);
   3449         if (count < 0)
   3450             return -1;
   3451         sum += count;
   3452     }
   3453 
   3454     count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
   3455     if (count < 0)
   3456         return -1;
   3457     sum += count;
   3458     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
   3459     if (count < 0)
   3460         return -1;
   3461     sum += count;
   3462 
   3463     return sum;
   3464 }
   3465 
   3466 /**
   3467  * xmlTextWriterEndDTDAttlist:
   3468  * @writer:  the xmlTextWriterPtr
   3469  *
   3470  * End an xml DTD attribute list.
   3471  *
   3472  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3473  */
   3474 int
   3475 xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
   3476 {
   3477     int count;
   3478     int sum;
   3479     xmlLinkPtr lk;
   3480     xmlTextWriterStackEntry *p;
   3481 
   3482     if (writer == NULL)
   3483         return -1;
   3484 
   3485     sum = 0;
   3486     lk = xmlListFront(writer->nodes);
   3487     if (lk == 0)
   3488         return -1;
   3489 
   3490     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   3491     if (p == 0)
   3492         return -1;
   3493 
   3494     switch (p->state) {
   3495         case XML_TEXTWRITER_DTD_ATTL:
   3496         case XML_TEXTWRITER_DTD_ATTL_TEXT:
   3497             count = xmlOutputBufferWriteString(writer->out, ">");
   3498             if (count < 0)
   3499                 return -1;
   3500             sum += count;
   3501             break;
   3502         default:
   3503             return -1;
   3504     }
   3505 
   3506     if (writer->indent) {
   3507         count = xmlOutputBufferWriteString(writer->out, "\n");
   3508         if (count < 0)
   3509             return -1;
   3510         sum += count;
   3511     }
   3512 
   3513     xmlListPopFront(writer->nodes);
   3514     return sum;
   3515 }
   3516 
   3517 /**
   3518  * xmlTextWriterWriteFormatDTDAttlist:
   3519  * @writer:  the xmlTextWriterPtr
   3520  * @name:  the name of the DTD ATTLIST
   3521  * @format:  format string (see printf)
   3522  * @...:  extra parameters for the format
   3523  *
   3524  * Write a formatted DTD ATTLIST.
   3525  *
   3526  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3527  */
   3528 int XMLCDECL
   3529 xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
   3530                                    const xmlChar * name,
   3531                                    const char *format, ...)
   3532 {
   3533     int rc;
   3534     va_list ap;
   3535 
   3536     va_start(ap, format);
   3537 
   3538     rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
   3539 
   3540     va_end(ap);
   3541     return rc;
   3542 }
   3543 
   3544 /**
   3545  * xmlTextWriterWriteVFormatDTDAttlist:
   3546  * @writer:  the xmlTextWriterPtr
   3547  * @name:  the name of the DTD ATTLIST
   3548  * @format:  format string (see printf)
   3549  * @argptr:  pointer to the first member of the variable argument list.
   3550  *
   3551  * Write a formatted DTD ATTLIST.
   3552  *
   3553  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3554  */
   3555 int
   3556 xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
   3557                                     const xmlChar * name,
   3558                                     const char *format, va_list argptr)
   3559 {
   3560     int rc;
   3561     xmlChar *buf;
   3562 
   3563     if (writer == NULL)
   3564         return -1;
   3565 
   3566     buf = xmlTextWriterVSprintf(format, argptr);
   3567     if (buf == NULL)
   3568         return -1;
   3569 
   3570     rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
   3571 
   3572     xmlFree(buf);
   3573     return rc;
   3574 }
   3575 
   3576 /**
   3577  * xmlTextWriterWriteDTDAttlist:
   3578  * @writer:  the xmlTextWriterPtr
   3579  * @name:  the name of the DTD ATTLIST
   3580  * @content:  content of the ATTLIST
   3581  *
   3582  * Write a DTD ATTLIST.
   3583  *
   3584  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3585  */
   3586 int
   3587 xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
   3588                              const xmlChar * name, const xmlChar * content)
   3589 {
   3590     int count;
   3591     int sum;
   3592 
   3593     if (content == NULL)
   3594         return -1;
   3595 
   3596     sum = 0;
   3597     count = xmlTextWriterStartDTDAttlist(writer, name);
   3598     if (count == -1)
   3599         return -1;
   3600     sum += count;
   3601 
   3602     count = xmlTextWriterWriteString(writer, content);
   3603     if (count == -1)
   3604         return -1;
   3605     sum += count;
   3606 
   3607     count = xmlTextWriterEndDTDAttlist(writer);
   3608     if (count == -1)
   3609         return -1;
   3610     sum += count;
   3611 
   3612     return sum;
   3613 }
   3614 
   3615 /**
   3616  * xmlTextWriterStartDTDEntity:
   3617  * @writer:  the xmlTextWriterPtr
   3618  * @pe:  TRUE if this is a parameter entity, FALSE if not
   3619  * @name:  the name of the DTD ATTLIST
   3620  *
   3621  * Start an xml DTD ATTLIST.
   3622  *
   3623  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3624  */
   3625 int
   3626 xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
   3627                             int pe, const xmlChar * name)
   3628 {
   3629     int count;
   3630     int sum;
   3631     xmlLinkPtr lk;
   3632     xmlTextWriterStackEntry *p;
   3633 
   3634     if (writer == NULL || name == NULL || *name == '\0')
   3635         return -1;
   3636 
   3637     sum = 0;
   3638     lk = xmlListFront(writer->nodes);
   3639     if (lk != 0) {
   3640 
   3641         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   3642         if (p != 0) {
   3643             switch (p->state) {
   3644                 case XML_TEXTWRITER_DTD:
   3645                     count = xmlOutputBufferWriteString(writer->out, " [");
   3646                     if (count < 0)
   3647                         return -1;
   3648                     sum += count;
   3649                     if (writer->indent) {
   3650                         count =
   3651                             xmlOutputBufferWriteString(writer->out, "\n");
   3652                         if (count < 0)
   3653                             return -1;
   3654                         sum += count;
   3655                     }
   3656                     p->state = XML_TEXTWRITER_DTD_TEXT;
   3657                     /* fallthrough */
   3658                 case XML_TEXTWRITER_DTD_TEXT:
   3659                 case XML_TEXTWRITER_NONE:
   3660                     break;
   3661                 default:
   3662                     return -1;
   3663             }
   3664         }
   3665     }
   3666 
   3667     p = (xmlTextWriterStackEntry *)
   3668         xmlMalloc(sizeof(xmlTextWriterStackEntry));
   3669     if (p == 0) {
   3670         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   3671                         "xmlTextWriterStartDTDElement : out of memory!\n");
   3672         return -1;
   3673     }
   3674 
   3675     p->name = xmlStrdup(name);
   3676     if (p->name == 0) {
   3677         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
   3678                         "xmlTextWriterStartDTDElement : out of memory!\n");
   3679         xmlFree(p);
   3680         return -1;
   3681     }
   3682 
   3683     if (pe != 0)
   3684         p->state = XML_TEXTWRITER_DTD_PENT;
   3685     else
   3686         p->state = XML_TEXTWRITER_DTD_ENTY;
   3687 
   3688     xmlListPushFront(writer->nodes, p);
   3689 
   3690     if (writer->indent) {
   3691         count = xmlTextWriterWriteIndent(writer);
   3692         if (count < 0)
   3693             return -1;
   3694         sum += count;
   3695     }
   3696 
   3697     count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
   3698     if (count < 0)
   3699         return -1;
   3700     sum += count;
   3701 
   3702     if (pe != 0) {
   3703         count = xmlOutputBufferWriteString(writer->out, "% ");
   3704         if (count < 0)
   3705             return -1;
   3706         sum += count;
   3707     }
   3708 
   3709     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
   3710     if (count < 0)
   3711         return -1;
   3712     sum += count;
   3713 
   3714     return sum;
   3715 }
   3716 
   3717 /**
   3718  * xmlTextWriterEndDTDEntity:
   3719  * @writer:  the xmlTextWriterPtr
   3720  *
   3721  * End an xml DTD entity.
   3722  *
   3723  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3724  */
   3725 int
   3726 xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
   3727 {
   3728     int count;
   3729     int sum;
   3730     xmlLinkPtr lk;
   3731     xmlTextWriterStackEntry *p;
   3732 
   3733     if (writer == NULL)
   3734         return -1;
   3735 
   3736     sum = 0;
   3737     lk = xmlListFront(writer->nodes);
   3738     if (lk == 0)
   3739         return -1;
   3740 
   3741     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   3742     if (p == 0)
   3743         return -1;
   3744 
   3745     switch (p->state) {
   3746         case XML_TEXTWRITER_DTD_ENTY_TEXT:
   3747             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   3748             if (count < 0)
   3749                 return -1;
   3750             sum += count;
   3751         case XML_TEXTWRITER_DTD_ENTY:
   3752         case XML_TEXTWRITER_DTD_PENT:
   3753             count = xmlOutputBufferWriteString(writer->out, ">");
   3754             if (count < 0)
   3755                 return -1;
   3756             sum += count;
   3757             break;
   3758         default:
   3759             return -1;
   3760     }
   3761 
   3762     if (writer->indent) {
   3763         count = xmlOutputBufferWriteString(writer->out, "\n");
   3764         if (count < 0)
   3765             return -1;
   3766         sum += count;
   3767     }
   3768 
   3769     xmlListPopFront(writer->nodes);
   3770     return sum;
   3771 }
   3772 
   3773 /**
   3774  * xmlTextWriterWriteFormatDTDInternalEntity:
   3775  * @writer:  the xmlTextWriterPtr
   3776  * @pe:  TRUE if this is a parameter entity, FALSE if not
   3777  * @name:  the name of the DTD entity
   3778  * @format:  format string (see printf)
   3779  * @...:  extra parameters for the format
   3780  *
   3781  * Write a formatted DTD internal entity.
   3782  *
   3783  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3784  */
   3785 int XMLCDECL
   3786 xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
   3787                                           int pe,
   3788                                           const xmlChar * name,
   3789                                           const char *format, ...)
   3790 {
   3791     int rc;
   3792     va_list ap;
   3793 
   3794     va_start(ap, format);
   3795 
   3796     rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
   3797                                                     format, ap);
   3798 
   3799     va_end(ap);
   3800     return rc;
   3801 }
   3802 
   3803 /**
   3804  * xmlTextWriterWriteVFormatDTDInternalEntity:
   3805  * @writer:  the xmlTextWriterPtr
   3806  * @pe:  TRUE if this is a parameter entity, FALSE if not
   3807  * @name:  the name of the DTD entity
   3808  * @format:  format string (see printf)
   3809  * @argptr:  pointer to the first member of the variable argument list.
   3810  *
   3811  * Write a formatted DTD internal entity.
   3812  *
   3813  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3814  */
   3815 int
   3816 xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
   3817                                            int pe,
   3818                                            const xmlChar * name,
   3819                                            const char *format,
   3820                                            va_list argptr)
   3821 {
   3822     int rc;
   3823     xmlChar *buf;
   3824 
   3825     if (writer == NULL)
   3826         return -1;
   3827 
   3828     buf = xmlTextWriterVSprintf(format, argptr);
   3829     if (buf == NULL)
   3830         return -1;
   3831 
   3832     rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
   3833 
   3834     xmlFree(buf);
   3835     return rc;
   3836 }
   3837 
   3838 /**
   3839  * xmlTextWriterWriteDTDEntity:
   3840  * @writer:  the xmlTextWriterPtr
   3841  * @pe:  TRUE if this is a parameter entity, FALSE if not
   3842  * @name:  the name of the DTD entity
   3843  * @pubid:  the public identifier, which is an alternative to the system identifier
   3844  * @sysid:  the system identifier, which is the URI of the DTD
   3845  * @ndataid:  the xml notation name.
   3846  * @content:  content of the entity
   3847  *
   3848  * Write a DTD entity.
   3849  *
   3850  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3851  */
   3852 int
   3853 xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
   3854                             int pe,
   3855                             const xmlChar * name,
   3856                             const xmlChar * pubid,
   3857                             const xmlChar * sysid,
   3858                             const xmlChar * ndataid,
   3859                             const xmlChar * content)
   3860 {
   3861     if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
   3862         return -1;
   3863     if ((pe != 0) && (ndataid != NULL))
   3864         return -1;
   3865 
   3866     if ((pubid == NULL) && (sysid == NULL))
   3867         return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
   3868                                                    content);
   3869 
   3870     return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
   3871                                                sysid, ndataid);
   3872 }
   3873 
   3874 /**
   3875  * xmlTextWriterWriteDTDInternalEntity:
   3876  * @writer:  the xmlTextWriterPtr
   3877  * @pe:  TRUE if this is a parameter entity, FALSE if not
   3878  * @name:  the name of the DTD entity
   3879  * @content:  content of the entity
   3880  *
   3881  * Write a DTD internal entity.
   3882  *
   3883  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3884  */
   3885 int
   3886 xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
   3887                                     int pe,
   3888                                     const xmlChar * name,
   3889                                     const xmlChar * content)
   3890 {
   3891     int count;
   3892     int sum;
   3893 
   3894     if ((name == NULL) || (*name == '\0') || (content == NULL))
   3895         return -1;
   3896 
   3897     sum = 0;
   3898     count = xmlTextWriterStartDTDEntity(writer, pe, name);
   3899     if (count == -1)
   3900         return -1;
   3901     sum += count;
   3902 
   3903     count = xmlTextWriterWriteString(writer, content);
   3904     if (count == -1)
   3905         return -1;
   3906     sum += count;
   3907 
   3908     count = xmlTextWriterEndDTDEntity(writer);
   3909     if (count == -1)
   3910         return -1;
   3911     sum += count;
   3912 
   3913     return sum;
   3914 }
   3915 
   3916 /**
   3917  * xmlTextWriterWriteDTDExternalEntity:
   3918  * @writer:  the xmlTextWriterPtr
   3919  * @pe:  TRUE if this is a parameter entity, FALSE if not
   3920  * @name:  the name of the DTD entity
   3921  * @pubid:  the public identifier, which is an alternative to the system identifier
   3922  * @sysid:  the system identifier, which is the URI of the DTD
   3923  * @ndataid:  the xml notation name.
   3924  *
   3925  * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
   3926  *
   3927  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3928  */
   3929 int
   3930 xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
   3931                                     int pe,
   3932                                     const xmlChar * name,
   3933                                     const xmlChar * pubid,
   3934                                     const xmlChar * sysid,
   3935                                     const xmlChar * ndataid)
   3936 {
   3937     int count;
   3938     int sum;
   3939 
   3940     if (((pubid == NULL) && (sysid == NULL)))
   3941         return -1;
   3942     if ((pe != 0) && (ndataid != NULL))
   3943         return -1;
   3944 
   3945     sum = 0;
   3946     count = xmlTextWriterStartDTDEntity(writer, pe, name);
   3947     if (count == -1)
   3948         return -1;
   3949     sum += count;
   3950 
   3951     count =
   3952         xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
   3953                                                     ndataid);
   3954     if (count < 0)
   3955         return -1;
   3956     sum += count;
   3957 
   3958     count = xmlTextWriterEndDTDEntity(writer);
   3959     if (count == -1)
   3960         return -1;
   3961     sum += count;
   3962 
   3963     return sum;
   3964 }
   3965 
   3966 /**
   3967  * xmlTextWriterWriteDTDExternalEntityContents:
   3968  * @writer:  the xmlTextWriterPtr
   3969  * @pubid:  the public identifier, which is an alternative to the system identifier
   3970  * @sysid:  the system identifier, which is the URI of the DTD
   3971  * @ndataid:  the xml notation name.
   3972  *
   3973  * Write the contents of a DTD external entity.
   3974  *
   3975  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   3976  */
   3977 int
   3978 xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
   3979                                             const xmlChar * pubid,
   3980                                             const xmlChar * sysid,
   3981                                             const xmlChar * ndataid)
   3982 {
   3983     int count;
   3984     int sum;
   3985     xmlLinkPtr lk;
   3986     xmlTextWriterStackEntry *p;
   3987 
   3988     if (writer == NULL) {
   3989         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   3990                         "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
   3991         return -1;
   3992     }
   3993 
   3994     sum = 0;
   3995     lk = xmlListFront(writer->nodes);
   3996     if (lk == 0) {
   3997         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   3998                         "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
   3999         return -1;
   4000     }
   4001 
   4002     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   4003     if (p == 0)
   4004         return -1;
   4005 
   4006     switch (p->state) {
   4007         case XML_TEXTWRITER_DTD_ENTY:
   4008             break;
   4009         case XML_TEXTWRITER_DTD_PENT:
   4010             if (ndataid != NULL) {
   4011                 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   4012                                 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
   4013                 return -1;
   4014             }
   4015             break;
   4016         default:
   4017             xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   4018                             "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
   4019             return -1;
   4020     }
   4021 
   4022     if (pubid != 0) {
   4023         if (sysid == 0) {
   4024             xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
   4025                             "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
   4026             return -1;
   4027         }
   4028 
   4029         count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
   4030         if (count < 0)
   4031             return -1;
   4032         sum += count;
   4033 
   4034         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4035         if (count < 0)
   4036             return -1;
   4037         sum += count;
   4038 
   4039         count =
   4040             xmlOutputBufferWriteString(writer->out, (const char *) pubid);
   4041         if (count < 0)
   4042             return -1;
   4043         sum += count;
   4044 
   4045         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4046         if (count < 0)
   4047             return -1;
   4048         sum += count;
   4049     }
   4050 
   4051     if (sysid != 0) {
   4052         if (pubid == 0) {
   4053             count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
   4054             if (count < 0)
   4055                 return -1;
   4056             sum += count;
   4057         }
   4058 
   4059         count = xmlOutputBufferWriteString(writer->out, " ");
   4060         if (count < 0)
   4061             return -1;
   4062         sum += count;
   4063 
   4064         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4065         if (count < 0)
   4066             return -1;
   4067         sum += count;
   4068 
   4069         count =
   4070             xmlOutputBufferWriteString(writer->out, (const char *) sysid);
   4071         if (count < 0)
   4072             return -1;
   4073         sum += count;
   4074 
   4075         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4076         if (count < 0)
   4077             return -1;
   4078         sum += count;
   4079     }
   4080 
   4081     if (ndataid != NULL) {
   4082         count = xmlOutputBufferWriteString(writer->out, " NDATA ");
   4083         if (count < 0)
   4084             return -1;
   4085         sum += count;
   4086 
   4087         count =
   4088             xmlOutputBufferWriteString(writer->out,
   4089                                        (const char *) ndataid);
   4090         if (count < 0)
   4091             return -1;
   4092         sum += count;
   4093     }
   4094 
   4095     return sum;
   4096 }
   4097 
   4098 /**
   4099  * xmlTextWriterWriteDTDNotation:
   4100  * @writer:  the xmlTextWriterPtr
   4101  * @name:  the name of the xml notation
   4102  * @pubid:  the public identifier, which is an alternative to the system identifier
   4103  * @sysid:  the system identifier, which is the URI of the DTD
   4104  *
   4105  * Write a DTD entity.
   4106  *
   4107  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   4108  */
   4109 int
   4110 xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
   4111                               const xmlChar * name,
   4112                               const xmlChar * pubid, const xmlChar * sysid)
   4113 {
   4114     int count;
   4115     int sum;
   4116     xmlLinkPtr lk;
   4117     xmlTextWriterStackEntry *p;
   4118 
   4119     if (writer == NULL || name == NULL || *name == '\0')
   4120         return -1;
   4121 
   4122     sum = 0;
   4123     lk = xmlListFront(writer->nodes);
   4124     if (lk == 0) {
   4125         return -1;
   4126     }
   4127 
   4128     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   4129     if (p != 0) {
   4130         switch (p->state) {
   4131             case XML_TEXTWRITER_DTD:
   4132                 count = xmlOutputBufferWriteString(writer->out, " [");
   4133                 if (count < 0)
   4134                     return -1;
   4135                 sum += count;
   4136                 if (writer->indent) {
   4137                     count = xmlOutputBufferWriteString(writer->out, "\n");
   4138                     if (count < 0)
   4139                         return -1;
   4140                     sum += count;
   4141                 }
   4142                 p->state = XML_TEXTWRITER_DTD_TEXT;
   4143                 /* fallthrough */
   4144             case XML_TEXTWRITER_DTD_TEXT:
   4145                 break;
   4146             default:
   4147                 return -1;
   4148         }
   4149     }
   4150 
   4151     if (writer->indent) {
   4152         count = xmlTextWriterWriteIndent(writer);
   4153         if (count < 0)
   4154             return -1;
   4155         sum += count;
   4156     }
   4157 
   4158     count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
   4159     if (count < 0)
   4160         return -1;
   4161     sum += count;
   4162     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
   4163     if (count < 0)
   4164         return -1;
   4165     sum += count;
   4166 
   4167     if (pubid != 0) {
   4168         count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
   4169         if (count < 0)
   4170             return -1;
   4171         sum += count;
   4172         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4173         if (count < 0)
   4174             return -1;
   4175         sum += count;
   4176         count =
   4177             xmlOutputBufferWriteString(writer->out, (const char *) pubid);
   4178         if (count < 0)
   4179             return -1;
   4180         sum += count;
   4181         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4182         if (count < 0)
   4183             return -1;
   4184         sum += count;
   4185     }
   4186 
   4187     if (sysid != 0) {
   4188         if (pubid == 0) {
   4189             count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
   4190             if (count < 0)
   4191                 return -1;
   4192             sum += count;
   4193         }
   4194         count = xmlOutputBufferWriteString(writer->out, " ");
   4195         if (count < 0)
   4196             return -1;
   4197         sum += count;
   4198         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4199         if (count < 0)
   4200             return -1;
   4201         sum += count;
   4202         count =
   4203             xmlOutputBufferWriteString(writer->out, (const char *) sysid);
   4204         if (count < 0)
   4205             return -1;
   4206         sum += count;
   4207         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
   4208         if (count < 0)
   4209             return -1;
   4210         sum += count;
   4211     }
   4212 
   4213     count = xmlOutputBufferWriteString(writer->out, ">");
   4214     if (count < 0)
   4215         return -1;
   4216     sum += count;
   4217 
   4218     return sum;
   4219 }
   4220 
   4221 /**
   4222  * xmlTextWriterFlush:
   4223  * @writer:  the xmlTextWriterPtr
   4224  *
   4225  * Flush the output buffer.
   4226  *
   4227  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
   4228  */
   4229 int
   4230 xmlTextWriterFlush(xmlTextWriterPtr writer)
   4231 {
   4232     int count;
   4233 
   4234     if (writer == NULL)
   4235         return -1;
   4236 
   4237     if (writer->out == NULL)
   4238         count = 0;
   4239     else
   4240         count = xmlOutputBufferFlush(writer->out);
   4241 
   4242     return count;
   4243 }
   4244 
   4245 /**
   4246  * misc
   4247  */
   4248 
   4249 /**
   4250  * xmlFreeTextWriterStackEntry:
   4251  * @lk:  the xmlLinkPtr
   4252  *
   4253  * Free callback for the xmlList.
   4254  */
   4255 static void
   4256 xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
   4257 {
   4258     xmlTextWriterStackEntry *p;
   4259 
   4260     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
   4261     if (p == 0)
   4262         return;
   4263 
   4264     if (p->name != 0)
   4265         xmlFree(p->name);
   4266     xmlFree(p);
   4267 }
   4268 
   4269 /**
   4270  * xmlCmpTextWriterStackEntry:
   4271  * @data0:  the first data
   4272  * @data1:  the second data
   4273  *
   4274  * Compare callback for the xmlList.
   4275  *
   4276  * Returns -1, 0, 1
   4277  */
   4278 static int
   4279 xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
   4280 {
   4281     xmlTextWriterStackEntry *p0;
   4282     xmlTextWriterStackEntry *p1;
   4283 
   4284     if (data0 == data1)
   4285         return 0;
   4286 
   4287     if (data0 == 0)
   4288         return -1;
   4289 
   4290     if (data1 == 0)
   4291         return 1;
   4292 
   4293     p0 = (xmlTextWriterStackEntry *) data0;
   4294     p1 = (xmlTextWriterStackEntry *) data1;
   4295 
   4296     return xmlStrcmp(p0->name, p1->name);
   4297 }
   4298 
   4299 /**
   4300  * misc
   4301  */
   4302 
   4303 /**
   4304  * xmlTextWriterOutputNSDecl:
   4305  * @writer:  the xmlTextWriterPtr
   4306  *
   4307  * Output the current namespace declarations.
   4308  */
   4309 static int
   4310 xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
   4311 {
   4312     xmlLinkPtr lk;
   4313     xmlTextWriterNsStackEntry *np;
   4314     int count;
   4315     int sum;
   4316 
   4317     sum = 0;
   4318     while (!xmlListEmpty(writer->nsstack)) {
   4319         xmlChar *namespaceURI = NULL;
   4320         xmlChar *prefix = NULL;
   4321 
   4322         lk = xmlListFront(writer->nsstack);
   4323         np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
   4324 
   4325         if (np != 0) {
   4326             namespaceURI = xmlStrdup(np->uri);
   4327             prefix = xmlStrdup(np->prefix);
   4328         }
   4329 
   4330         xmlListPopFront(writer->nsstack);
   4331 
   4332         if (np != 0) {
   4333             count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
   4334             xmlFree(namespaceURI);
   4335             xmlFree(prefix);
   4336 
   4337             if (count < 0) {
   4338                 xmlListDelete(writer->nsstack);
   4339                 writer->nsstack = NULL;
   4340                 return -1;
   4341             }
   4342             sum += count;
   4343         }
   4344     }
   4345     return sum;
   4346 }
   4347 
   4348 /**
   4349  * xmlFreeTextWriterNsStackEntry:
   4350  * @lk:  the xmlLinkPtr
   4351  *
   4352  * Free callback for the xmlList.
   4353  */
   4354 static void
   4355 xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
   4356 {
   4357     xmlTextWriterNsStackEntry *p;
   4358 
   4359     p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
   4360     if (p == 0)
   4361         return;
   4362 
   4363     if (p->prefix != 0)
   4364         xmlFree(p->prefix);
   4365     if (p->uri != 0)
   4366         xmlFree(p->uri);
   4367 
   4368     xmlFree(p);
   4369 }
   4370 
   4371 /**
   4372  * xmlCmpTextWriterNsStackEntry:
   4373  * @data0:  the first data
   4374  * @data1:  the second data
   4375  *
   4376  * Compare callback for the xmlList.
   4377  *
   4378  * Returns -1, 0, 1
   4379  */
   4380 static int
   4381 xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
   4382 {
   4383     xmlTextWriterNsStackEntry *p0;
   4384     xmlTextWriterNsStackEntry *p1;
   4385     int rc;
   4386 
   4387     if (data0 == data1)
   4388         return 0;
   4389 
   4390     if (data0 == 0)
   4391         return -1;
   4392 
   4393     if (data1 == 0)
   4394         return 1;
   4395 
   4396     p0 = (xmlTextWriterNsStackEntry *) data0;
   4397     p1 = (xmlTextWriterNsStackEntry *) data1;
   4398 
   4399     rc = xmlStrcmp(p0->prefix, p1->prefix);
   4400 
   4401     if ((rc != 0) || (p0->elem != p1->elem))
   4402         rc = -1;
   4403 
   4404     return rc;
   4405 }
   4406 
   4407 /**
   4408  * xmlTextWriterWriteDocCallback:
   4409  * @context:  the xmlBufferPtr
   4410  * @str:  the data to write
   4411  * @len:  the length of the data
   4412  *
   4413  * Write callback for the xmlOutputBuffer with target xmlBuffer
   4414  *
   4415  * Returns -1, 0, 1
   4416  */
   4417 static int
   4418 xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
   4419 {
   4420     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
   4421     int rc;
   4422 
   4423     if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
   4424         xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
   4425                         "xmlTextWriterWriteDocCallback : XML error %d !\n",
   4426                         rc);
   4427         return -1;
   4428     }
   4429 
   4430     return len;
   4431 }
   4432 
   4433 /**
   4434  * xmlTextWriterCloseDocCallback:
   4435  * @context:  the xmlBufferPtr
   4436  *
   4437  * Close callback for the xmlOutputBuffer with target xmlBuffer
   4438  *
   4439  * Returns -1, 0, 1
   4440  */
   4441 static int
   4442 xmlTextWriterCloseDocCallback(void *context)
   4443 {
   4444     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
   4445     int rc;
   4446 
   4447     if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
   4448         xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
   4449                         "xmlTextWriterWriteDocCallback : XML error %d !\n",
   4450                         rc);
   4451         return -1;
   4452     }
   4453 
   4454     return 0;
   4455 }
   4456 
   4457 /**
   4458  * xmlTextWriterVSprintf:
   4459  * @format:  see printf
   4460  * @argptr:  pointer to the first member of the variable argument list.
   4461  *
   4462  * Utility function for formatted output
   4463  *
   4464  * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
   4465  */
   4466 static xmlChar *
   4467 xmlTextWriterVSprintf(const char *format, va_list argptr)
   4468 {
   4469     int size;
   4470     int count;
   4471     xmlChar *buf;
   4472     va_list locarg;
   4473 
   4474     size = BUFSIZ;
   4475     buf = (xmlChar *) xmlMalloc(size);
   4476     if (buf == NULL) {
   4477         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
   4478                         "xmlTextWriterVSprintf : out of memory!\n");
   4479         return NULL;
   4480     }
   4481 
   4482     VA_COPY(locarg, argptr);
   4483     while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
   4484            || (count == size - 1) || (count == size) || (count > size)) {
   4485 	va_end(locarg);
   4486         xmlFree(buf);
   4487         size += BUFSIZ;
   4488         buf = (xmlChar *) xmlMalloc(size);
   4489         if (buf == NULL) {
   4490             xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
   4491                             "xmlTextWriterVSprintf : out of memory!\n");
   4492             return NULL;
   4493         }
   4494 	VA_COPY(locarg, argptr);
   4495     }
   4496     va_end(locarg);
   4497 
   4498     return buf;
   4499 }
   4500 
   4501 /**
   4502  * xmlTextWriterStartDocumentCallback:
   4503  * @ctx: the user data (XML parser context)
   4504  *
   4505  * called at the start of document processing.
   4506  */
   4507 static void
   4508 xmlTextWriterStartDocumentCallback(void *ctx)
   4509 {
   4510     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   4511     xmlDocPtr doc;
   4512 
   4513     if (ctxt->html) {
   4514 #ifdef LIBXML_HTML_ENABLED
   4515         if (ctxt->myDoc == NULL)
   4516             ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
   4517         if (ctxt->myDoc == NULL) {
   4518             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
   4519                 ctxt->sax->error(ctxt->userData,
   4520                                  "SAX.startDocument(): out of memory\n");
   4521             ctxt->errNo = XML_ERR_NO_MEMORY;
   4522             ctxt->instate = XML_PARSER_EOF;
   4523             ctxt->disableSAX = 1;
   4524             return;
   4525         }
   4526 #else
   4527         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
   4528                         "libxml2 built without HTML support\n");
   4529         ctxt->errNo = XML_ERR_INTERNAL_ERROR;
   4530         ctxt->instate = XML_PARSER_EOF;
   4531         ctxt->disableSAX = 1;
   4532         return;
   4533 #endif
   4534     } else {
   4535         doc = ctxt->myDoc;
   4536         if (doc == NULL)
   4537             doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
   4538         if (doc != NULL) {
   4539             if (doc->children == NULL) {
   4540                 if (ctxt->encoding != NULL)
   4541                     doc->encoding = xmlStrdup(ctxt->encoding);
   4542                 else
   4543                     doc->encoding = NULL;
   4544                 doc->standalone = ctxt->standalone;
   4545             }
   4546         } else {
   4547             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
   4548                 ctxt->sax->error(ctxt->userData,
   4549                                  "SAX.startDocument(): out of memory\n");
   4550             ctxt->errNo = XML_ERR_NO_MEMORY;
   4551             ctxt->instate = XML_PARSER_EOF;
   4552             ctxt->disableSAX = 1;
   4553             return;
   4554         }
   4555     }
   4556     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
   4557         (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
   4558         ctxt->myDoc->URL =
   4559             xmlCanonicPath((const xmlChar *) ctxt->input->filename);
   4560         if (ctxt->myDoc->URL == NULL)
   4561             ctxt->myDoc->URL =
   4562                 xmlStrdup((const xmlChar *) ctxt->input->filename);
   4563     }
   4564 }
   4565 
   4566 /**
   4567  * xmlTextWriterSetIndent:
   4568  * @writer:  the xmlTextWriterPtr
   4569  * @indent:  do indentation?
   4570  *
   4571  * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
   4572  *
   4573  * Returns -1 on error or 0 otherwise.
   4574  */
   4575 int
   4576 xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
   4577 {
   4578     if ((writer == NULL) || (indent < 0))
   4579         return -1;
   4580 
   4581     writer->indent = indent;
   4582     writer->doindent = 1;
   4583 
   4584     return 0;
   4585 }
   4586 
   4587 /**
   4588  * xmlTextWriterSetIndentString:
   4589  * @writer:  the xmlTextWriterPtr
   4590  * @str:  the xmlChar string
   4591  *
   4592  * Set string indentation.
   4593  *
   4594  * Returns -1 on error or 0 otherwise.
   4595  */
   4596 int
   4597 xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
   4598 {
   4599     if ((writer == NULL) || (!str))
   4600         return -1;
   4601 
   4602     if (writer->ichar != NULL)
   4603         xmlFree(writer->ichar);
   4604     writer->ichar = xmlStrdup(str);
   4605 
   4606     if (!writer->ichar)
   4607         return -1;
   4608     else
   4609         return 0;
   4610 }
   4611 
   4612 /**
   4613  * xmlTextWriterSetQuoteChar:
   4614  * @writer:  the xmlTextWriterPtr
   4615  * @quotechar:  the quote character
   4616  *
   4617  * Set the character used for quoting attributes.
   4618  *
   4619  * Returns -1 on error or 0 otherwise.
   4620  */
   4621 int
   4622 xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
   4623 {
   4624     if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
   4625         return -1;
   4626 
   4627     writer->qchar = quotechar;
   4628 
   4629     return 0;
   4630 }
   4631 
   4632 /**
   4633  * xmlTextWriterWriteIndent:
   4634  * @writer:  the xmlTextWriterPtr
   4635  *
   4636  * Write indent string.
   4637  *
   4638  * Returns -1 on error or the number of strings written.
   4639  */
   4640 static int
   4641 xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
   4642 {
   4643     int lksize;
   4644     int i;
   4645     int ret;
   4646 
   4647     lksize = xmlListSize(writer->nodes);
   4648     if (lksize < 1)
   4649         return (-1);            /* list is empty */
   4650     for (i = 0; i < (lksize - 1); i++) {
   4651         ret = xmlOutputBufferWriteString(writer->out,
   4652                                          (const char *) writer->ichar);
   4653         if (ret == -1)
   4654             return (-1);
   4655     }
   4656 
   4657     return (lksize - 1);
   4658 }
   4659 
   4660 /**
   4661  * xmlTextWriterHandleStateDependencies:
   4662  * @writer:  the xmlTextWriterPtr
   4663  * @p:  the xmlTextWriterStackEntry
   4664  *
   4665  * Write state dependent strings.
   4666  *
   4667  * Returns -1 on error or the number of characters written.
   4668  */
   4669 static int
   4670 xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
   4671                                      xmlTextWriterStackEntry * p)
   4672 {
   4673     int count;
   4674     int sum;
   4675     char extra[3];
   4676 
   4677     if (writer == NULL)
   4678         return -1;
   4679 
   4680     if (p == NULL)
   4681         return 0;
   4682 
   4683     sum = 0;
   4684     extra[0] = extra[1] = extra[2] = '\0';
   4685     if (p != 0) {
   4686         sum = 0;
   4687         switch (p->state) {
   4688             case XML_TEXTWRITER_NAME:
   4689                 /* Output namespace declarations */
   4690                 count = xmlTextWriterOutputNSDecl(writer);
   4691                 if (count < 0)
   4692                     return -1;
   4693                 sum += count;
   4694                 extra[0] = '>';
   4695                 p->state = XML_TEXTWRITER_TEXT;
   4696                 break;
   4697             case XML_TEXTWRITER_PI:
   4698                 extra[0] = ' ';
   4699                 p->state = XML_TEXTWRITER_PI_TEXT;
   4700                 break;
   4701             case XML_TEXTWRITER_DTD:
   4702                 extra[0] = ' ';
   4703                 extra[1] = '[';
   4704                 p->state = XML_TEXTWRITER_DTD_TEXT;
   4705                 break;
   4706             case XML_TEXTWRITER_DTD_ELEM:
   4707                 extra[0] = ' ';
   4708                 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
   4709                 break;
   4710             case XML_TEXTWRITER_DTD_ATTL:
   4711                 extra[0] = ' ';
   4712                 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
   4713                 break;
   4714             case XML_TEXTWRITER_DTD_ENTY:
   4715             case XML_TEXTWRITER_DTD_PENT:
   4716                 extra[0] = ' ';
   4717                 extra[1] = writer->qchar;
   4718                 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
   4719                 break;
   4720             default:
   4721                 break;
   4722         }
   4723     }
   4724 
   4725     if (*extra != '\0') {
   4726         count = xmlOutputBufferWriteString(writer->out, extra);
   4727         if (count < 0)
   4728             return -1;
   4729         sum += count;
   4730     }
   4731 
   4732     return sum;
   4733 }
   4734 
   4735 #define bottom_xmlwriter
   4736 #include "elfgcchack.h"
   4737 #endif
   4738