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