source: trunk/third/libxml2/xmlwriter.c @ 21532

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