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