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