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