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