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