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