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