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