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