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