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