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