parser.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:295k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1.     /*
  2.      * We should be at the end of the DOCTYPE declaration.
  3.      */
  4.     if (RAW != '>') {
  5. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  6.     ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminatedn");
  7. ctxt->wellFormed = 0;
  8. ctxt->disableSAX = 1;
  9. ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
  10.     }
  11.     NEXT;
  12. }
  13. /**
  14.  * xmlParseAttribute:
  15.  * @ctxt:  an XML parser context
  16.  * @value:  a xmlChar ** used to store the value of the attribute
  17.  *
  18.  * parse an attribute
  19.  *
  20.  * [41] Attribute ::= Name Eq AttValue
  21.  *
  22.  * [ WFC: No External Entity References ]
  23.  * Attribute values cannot contain direct or indirect entity references
  24.  * to external entities.
  25.  *
  26.  * [ WFC: No < in Attribute Values ]
  27.  * The replacement text of any entity referred to directly or indirectly in
  28.  * an attribute value (other than "&lt;") must not contain a <. 
  29.  * 
  30.  * [ VC: Attribute Value Type ]
  31.  * The attribute must have been declared; the value must be of the type
  32.  * declared for it.
  33.  *
  34.  * [25] Eq ::= S? '=' S?
  35.  *
  36.  * With namespace:
  37.  *
  38.  * [NS 11] Attribute ::= QName Eq AttValue
  39.  *
  40.  * Also the case QName == xmlns:??? is handled independently as a namespace
  41.  * definition.
  42.  *
  43.  * Returns the attribute name, and the value in *value.
  44.  */
  45. xmlChar *
  46. xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
  47.     xmlChar *name, *val;
  48.     *value = NULL;
  49.     name = xmlParseName(ctxt);
  50.     if (name == NULL) {
  51. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  52.     ctxt->sax->error(ctxt->userData, "error parsing attribute namen");
  53. ctxt->wellFormed = 0;
  54. ctxt->disableSAX = 1;
  55. ctxt->errNo = XML_ERR_NAME_REQUIRED;
  56.         return(NULL);
  57.     }
  58.     /*
  59.      * read the value
  60.      */
  61.     SKIP_BLANKS;
  62.     if (RAW == '=') {
  63.         NEXT;
  64. SKIP_BLANKS;
  65. val = xmlParseAttValue(ctxt);
  66. ctxt->instate = XML_PARSER_CONTENT;
  67.     } else {
  68. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  69.     ctxt->sax->error(ctxt->userData,
  70.        "Specification mandate value for attribute %sn", name);
  71. ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
  72. ctxt->wellFormed = 0;
  73. ctxt->disableSAX = 1;
  74. xmlFree(name);
  75. return(NULL);
  76.     }
  77.     /*
  78.      * Check that xml:lang conforms to the specification
  79.      */
  80.     if (!xmlStrcmp(name, BAD_CAST "xml:lang")) {
  81. if (!xmlCheckLanguageID(val)) {
  82.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  83. ctxt->sax->error(ctxt->userData,
  84.    "Invalid value for xml:lang : %sn", val);
  85.     ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
  86.     ctxt->wellFormed = 0;
  87.     ctxt->disableSAX = 1;
  88. }
  89.     }
  90.     /*
  91.      * Check that xml:space conforms to the specification
  92.      */
  93.     if (!xmlStrcmp(name, BAD_CAST "xml:space")) {
  94. if (!xmlStrcmp(val, BAD_CAST "default"))
  95.     *(ctxt->space) = 0;
  96. else if (!xmlStrcmp(val, BAD_CAST "preserve"))
  97.     *(ctxt->space) = 1;
  98. else {
  99.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  100. ctxt->sax->error(ctxt->userData,
  101. "Invalid value for xml:space : "%s", "default" or "preserve" expectedn",
  102.                                  val);
  103.     ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
  104.     ctxt->wellFormed = 0;
  105.     ctxt->disableSAX = 1;
  106. }
  107.     }
  108.     *value = val;
  109.     return(name);
  110. }
  111. /**
  112.  * xmlParseStartTag:
  113.  * @ctxt:  an XML parser context
  114.  * 
  115.  * parse a start of tag either for rule element or
  116.  * EmptyElement. In both case we don't parse the tag closing chars.
  117.  *
  118.  * [40] STag ::= '<' Name (S Attribute)* S? '>'
  119.  *
  120.  * [ WFC: Unique Att Spec ]
  121.  * No attribute name may appear more than once in the same start-tag or
  122.  * empty-element tag. 
  123.  *
  124.  * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
  125.  *
  126.  * [ WFC: Unique Att Spec ]
  127.  * No attribute name may appear more than once in the same start-tag or
  128.  * empty-element tag. 
  129.  *
  130.  * With namespace:
  131.  *
  132.  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
  133.  *
  134.  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
  135.  *
  136.  * Returne the element name parsed
  137.  */
  138. xmlChar *
  139. xmlParseStartTag(xmlParserCtxtPtr ctxt) {
  140.     xmlChar *name;
  141.     xmlChar *attname;
  142.     xmlChar *attvalue;
  143.     const xmlChar **atts = NULL;
  144.     int nbatts = 0;
  145.     int maxatts = 0;
  146.     int i;
  147.     if (RAW != '<') return(NULL);
  148.     NEXT;
  149.     name = xmlParseName(ctxt);
  150.     if (name == NULL) {
  151. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  152.     ctxt->sax->error(ctxt->userData, 
  153.      "xmlParseStartTag: invalid element namen");
  154. ctxt->errNo = XML_ERR_NAME_REQUIRED;
  155. ctxt->wellFormed = 0;
  156. ctxt->disableSAX = 1;
  157.         return(NULL);
  158.     }
  159.     /*
  160.      * Now parse the attributes, it ends up with the ending
  161.      *
  162.      * (S Attribute)* S?
  163.      */
  164.     SKIP_BLANKS;
  165.     GROW;
  166.     while ((IS_CHAR(RAW)) &&
  167.            (RAW != '>') && 
  168.    ((RAW != '/') || (NXT(1) != '>'))) {
  169. const xmlChar *q = CUR_PTR;
  170. int cons = ctxt->input->consumed;
  171. attname = xmlParseAttribute(ctxt, &attvalue);
  172.         if ((attname != NULL) && (attvalue != NULL)) {
  173.     /*
  174.      * [ WFC: Unique Att Spec ]
  175.      * No attribute name may appear more than once in the same
  176.      * start-tag or empty-element tag. 
  177.      */
  178.     for (i = 0; i < nbatts;i += 2) {
  179.         if (!xmlStrcmp(atts[i], attname)) {
  180.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  181. ctxt->sax->error(ctxt->userData,
  182.         "Attribute %s redefinedn",
  183.                  attname);
  184.     ctxt->wellFormed = 0;
  185.     ctxt->disableSAX = 1;
  186.     ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
  187.     xmlFree(attname);
  188.     xmlFree(attvalue);
  189.     goto failed;
  190. }
  191.     }
  192.     /*
  193.      * Add the pair to atts
  194.      */
  195.     if (atts == NULL) {
  196.         maxatts = 10;
  197.         atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
  198. if (atts == NULL) {
  199.     fprintf(stderr, "malloc of %ld byte failedn",
  200.     maxatts * (long)sizeof(xmlChar *));
  201.     return(NULL);
  202. }
  203.     } else if (nbatts + 4 > maxatts) {
  204.         maxatts *= 2;
  205.         atts = (const xmlChar **) xmlRealloc(atts,
  206.                                   maxatts * sizeof(xmlChar *));
  207. if (atts == NULL) {
  208.     fprintf(stderr, "realloc of %ld byte failedn",
  209.     maxatts * (long)sizeof(xmlChar *));
  210.     return(NULL);
  211. }
  212.     }
  213.     atts[nbatts++] = attname;
  214.     atts[nbatts++] = attvalue;
  215.     atts[nbatts] = NULL;
  216.     atts[nbatts + 1] = NULL;
  217. } else {
  218.     if (attname != NULL)
  219. xmlFree(attname);
  220.     if (attvalue != NULL)
  221. xmlFree(attvalue);
  222. }
  223. failed:     
  224. if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
  225.     break;
  226. if (!IS_BLANK(RAW)) {
  227.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  228. ctxt->sax->error(ctxt->userData,
  229.     "attributes construct errorn");
  230.     ctxt->errNo = XML_ERR_SPACE_REQUIRED;
  231.     ctxt->wellFormed = 0;
  232.     ctxt->disableSAX = 1;
  233. }
  234. SKIP_BLANKS;
  235.         if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
  236.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  237.         ctxt->sax->error(ctxt->userData, 
  238.          "xmlParseStartTag: problem parsing attributesn");
  239.     ctxt->errNo = XML_ERR_INTERNAL_ERROR;
  240.     ctxt->wellFormed = 0;
  241.     ctxt->disableSAX = 1;
  242.     break;
  243. }
  244.         GROW;
  245.     }
  246.     /*
  247.      * SAX: Start of Element !
  248.      */
  249.     if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
  250. (!ctxt->disableSAX))
  251.         ctxt->sax->startElement(ctxt->userData, name, atts);
  252.     if (atts != NULL) {
  253.         for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
  254. xmlFree(atts);
  255.     }
  256.     return(name);
  257. }
  258. /**
  259.  * xmlParseEndTag:
  260.  * @ctxt:  an XML parser context
  261.  *
  262.  * parse an end of tag
  263.  *
  264.  * [42] ETag ::= '</' Name S? '>'
  265.  *
  266.  * With namespace
  267.  *
  268.  * [NS 9] ETag ::= '</' QName S? '>'
  269.  */
  270. void
  271. xmlParseEndTag(xmlParserCtxtPtr ctxt) {
  272.     xmlChar *name;
  273.     xmlChar *oldname;
  274.     GROW;
  275.     if ((RAW != '<') || (NXT(1) != '/')) {
  276. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  277.     ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not foundn");
  278. ctxt->wellFormed = 0;
  279. ctxt->disableSAX = 1;
  280. ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
  281. return;
  282.     }
  283.     SKIP(2);
  284.     name = xmlParseName(ctxt);
  285.     /*
  286.      * We should definitely be at the ending "S? '>'" part
  287.      */
  288.     GROW;
  289.     SKIP_BLANKS;
  290.     if ((!IS_CHAR(RAW)) || (RAW != '>')) {
  291. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  292.     ctxt->sax->error(ctxt->userData, "End tag : expected '>'n");
  293. ctxt->errNo = XML_ERR_GT_REQUIRED;
  294. ctxt->wellFormed = 0;
  295. ctxt->disableSAX = 1;
  296.     } else
  297. NEXT;
  298.     /*
  299.      * [ WFC: Element Type Match ]
  300.      * The Name in an element's end-tag must match the element type in the
  301.      * start-tag. 
  302.      *
  303.      */
  304.     if ((name == NULL) || (ctxt->name == NULL) ||
  305.         (xmlStrcmp(name, ctxt->name))) {
  306. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
  307.     if ((name != NULL) && (ctxt->name != NULL)) {
  308. ctxt->sax->error(ctxt->userData,
  309.      "Opening and ending tag mismatch: %s and %sn",
  310.                  ctxt->name, name);
  311.             } else if (ctxt->name != NULL) {
  312. ctxt->sax->error(ctxt->userData,
  313.      "Ending tag eror for: %sn", ctxt->name);
  314.     } else {
  315. ctxt->sax->error(ctxt->userData,
  316.      "Ending tag error: internal error ???n");
  317.     }
  318. }     
  319. ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
  320. ctxt->wellFormed = 0;
  321. ctxt->disableSAX = 1;
  322.     }
  323.     /*
  324.      * SAX: End of Tag
  325.      */
  326.     if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
  327. (!ctxt->disableSAX))
  328.         ctxt->sax->endElement(ctxt->userData, name);
  329.     if (name != NULL)
  330. xmlFree(name);
  331.     oldname = namePop(ctxt);
  332.     spacePop(ctxt);
  333.     if (oldname != NULL) {
  334. #ifdef DEBUG_STACK
  335. fprintf(stderr,"Close: popped %sn", oldname);
  336. #endif
  337. xmlFree(oldname);
  338.     }
  339.     return;
  340. }
  341. /**
  342.  * xmlParseCDSect:
  343.  * @ctxt:  an XML parser context
  344.  * 
  345.  * Parse escaped pure raw content.
  346.  *
  347.  * [18] CDSect ::= CDStart CData CDEnd
  348.  *
  349.  * [19] CDStart ::= '<![CDATA['
  350.  *
  351.  * [20] Data ::= (Char* - (Char* ']]>' Char*))
  352.  *
  353.  * [21] CDEnd ::= ']]>'
  354.  */
  355. void
  356. xmlParseCDSect(xmlParserCtxtPtr ctxt) {
  357.     xmlChar *buf = NULL;
  358.     int len = 0;
  359.     int size = XML_PARSER_BUFFER_SIZE;
  360.     int r, rl;
  361.     int s, sl;
  362.     int cur, l;
  363.     if ((NXT(0) == '<') && (NXT(1) == '!') &&
  364. (NXT(2) == '[') && (NXT(3) == 'C') &&
  365. (NXT(4) == 'D') && (NXT(5) == 'A') &&
  366. (NXT(6) == 'T') && (NXT(7) == 'A') &&
  367. (NXT(8) == '[')) {
  368. SKIP(9);
  369.     } else
  370.         return;
  371.     ctxt->instate = XML_PARSER_CDATA_SECTION;
  372.     r = CUR_CHAR(rl);
  373.     if (!IS_CHAR(r)) {
  374. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  375.     ctxt->sax->error(ctxt->userData,
  376.                      "CData section not finishedn");
  377. ctxt->wellFormed = 0;
  378. ctxt->disableSAX = 1;
  379. ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
  380. ctxt->instate = XML_PARSER_CONTENT;
  381.         return;
  382.     }
  383.     NEXTL(rl);
  384.     s = CUR_CHAR(sl);
  385.     if (!IS_CHAR(s)) {
  386. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  387.     ctxt->sax->error(ctxt->userData,
  388.                      "CData section not finishedn");
  389. ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
  390. ctxt->wellFormed = 0;
  391. ctxt->disableSAX = 1;
  392. ctxt->instate = XML_PARSER_CONTENT;
  393.         return;
  394.     }
  395.     NEXTL(sl);
  396.     cur = CUR_CHAR(l);
  397.     buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
  398.     if (buf == NULL) {
  399. fprintf(stderr, "malloc of %d byte failedn", size);
  400. return;
  401.     }
  402.     while (IS_CHAR(cur) &&
  403.            ((r != ']') || (s != ']') || (cur != '>'))) {
  404. if (len + 5 >= size) {
  405.     size *= 2;
  406.     buf = xmlRealloc(buf, size * sizeof(xmlChar));
  407.     if (buf == NULL) {
  408. fprintf(stderr, "realloc of %d byte failedn", size);
  409. return;
  410.     }
  411. }
  412. COPY_BUF(rl,buf,len,r);
  413. r = s;
  414. rl = sl;
  415. s = cur;
  416. sl = l;
  417. NEXTL(l);
  418. cur = CUR_CHAR(l);
  419.     }
  420.     buf[len] = 0;
  421.     ctxt->instate = XML_PARSER_CONTENT;
  422.     if (cur != '>') {
  423. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  424.     ctxt->sax->error(ctxt->userData,
  425.                      "CData section not finishedn%.50sn", buf);
  426. ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
  427. ctxt->wellFormed = 0;
  428. ctxt->disableSAX = 1;
  429. xmlFree(buf);
  430.         return;
  431.     }
  432.     NEXTL(l);
  433.     /*
  434.      * Ok the buffer is to be consumed as cdata.
  435.      */
  436.     if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
  437. if (ctxt->sax->cdataBlock != NULL)
  438.     ctxt->sax->cdataBlock(ctxt->userData, buf, len);
  439.     }
  440.     xmlFree(buf);
  441. }
  442. /**
  443.  * xmlParseContent:
  444.  * @ctxt:  an XML parser context
  445.  *
  446.  * Parse a content:
  447.  *
  448.  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
  449.  */
  450. void
  451. xmlParseContent(xmlParserCtxtPtr ctxt) {
  452.     GROW;
  453.     while (((RAW != 0) || (ctxt->token != 0)) &&
  454.    ((RAW != '<') || (NXT(1) != '/'))) {
  455. const xmlChar *test = CUR_PTR;
  456. int cons = ctxt->input->consumed;
  457. xmlChar tok = ctxt->token;
  458. /*
  459.  * Handle  possible processed charrefs.
  460.  */
  461. if (ctxt->token != 0) {
  462.     xmlParseCharData(ctxt, 0);
  463. }
  464. /*
  465.  * First case : a Processing Instruction.
  466.  */
  467. else if ((RAW == '<') && (NXT(1) == '?')) {
  468.     xmlParsePI(ctxt);
  469. }
  470. /*
  471.  * Second case : a CDSection
  472.  */
  473. else if ((RAW == '<') && (NXT(1) == '!') &&
  474.     (NXT(2) == '[') && (NXT(3) == 'C') &&
  475.     (NXT(4) == 'D') && (NXT(5) == 'A') &&
  476.     (NXT(6) == 'T') && (NXT(7) == 'A') &&
  477.     (NXT(8) == '[')) {
  478.     xmlParseCDSect(ctxt);
  479. }
  480. /*
  481.  * Third case :  a comment
  482.  */
  483. else if ((RAW == '<') && (NXT(1) == '!') &&
  484.  (NXT(2) == '-') && (NXT(3) == '-')) {
  485.     xmlParseComment(ctxt);
  486.     ctxt->instate = XML_PARSER_CONTENT;
  487. }
  488. /*
  489.  * Fourth case :  a sub-element.
  490.  */
  491. else if (RAW == '<') {
  492.     xmlParseElement(ctxt);
  493. }
  494. /*
  495.  * Fifth case : a reference. If if has not been resolved,
  496.  *    parsing returns it's Name, create the node 
  497.  */
  498. else if (RAW == '&') {
  499.     xmlParseReference(ctxt);
  500. }
  501. /*
  502.  * Last case, text. Note that References are handled directly.
  503.  */
  504. else {
  505.     xmlParseCharData(ctxt, 0);
  506. }
  507. GROW;
  508. /*
  509.  * Pop-up of finished entities.
  510.  */
  511. while ((RAW == 0) && (ctxt->inputNr > 1))
  512.     xmlPopInput(ctxt);
  513. SHRINK;
  514. if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
  515.     (tok == ctxt->token)) {
  516.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  517.         ctxt->sax->error(ctxt->userData,
  518.      "detected an error in element contentn");
  519.     ctxt->errNo = XML_ERR_INTERNAL_ERROR;
  520.     ctxt->wellFormed = 0;
  521.     ctxt->disableSAX = 1;
  522.             break;
  523. }
  524.     }
  525. }
  526. /**
  527.  * xmlParseElement:
  528.  * @ctxt:  an XML parser context
  529.  *
  530.  * parse an XML element, this is highly recursive
  531.  *
  532.  * [39] element ::= EmptyElemTag | STag content ETag
  533.  *
  534.  * [ WFC: Element Type Match ]
  535.  * The Name in an element's end-tag must match the element type in the
  536.  * start-tag. 
  537.  *
  538.  * [ VC: Element Valid ]
  539.  * An element is valid if there is a declaration matching elementdecl
  540.  * where the Name matches the element type and one of the following holds:
  541.  *  - The declaration matches EMPTY and the element has no content.
  542.  *  - The declaration matches children and the sequence of child elements
  543.  *    belongs to the language generated by the regular expression in the
  544.  *    content model, with optional white space (characters matching the
  545.  *    nonterminal S) between each pair of child elements. 
  546.  *  - The declaration matches Mixed and the content consists of character
  547.  *    data and child elements whose types match names in the content model. 
  548.  *  - The declaration matches ANY, and the types of any child elements have
  549.  *    been declared.
  550.  */
  551. void
  552. xmlParseElement(xmlParserCtxtPtr ctxt) {
  553.     const xmlChar *openTag = CUR_PTR;
  554.     xmlChar *name;
  555.     xmlChar *oldname;
  556.     xmlParserNodeInfo node_info;
  557.     xmlNodePtr ret;
  558.     /* Capture start position */
  559.     if (ctxt->record_info) {
  560.         node_info.begin_pos = ctxt->input->consumed +
  561.                           (CUR_PTR - ctxt->input->base);
  562. node_info.begin_line = ctxt->input->line;
  563.     }
  564.     if (ctxt->spaceNr == 0)
  565. spacePush(ctxt, -1);
  566.     else
  567. spacePush(ctxt, *ctxt->space);
  568.     name = xmlParseStartTag(ctxt);
  569.     if (name == NULL) {
  570. spacePop(ctxt);
  571.         return;
  572.     }
  573.     namePush(ctxt, name);
  574.     ret = ctxt->node;
  575.     /*
  576.      * [ VC: Root Element Type ]
  577.      * The Name in the document type declaration must match the element
  578.      * type of the root element. 
  579.      */
  580.     if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
  581.         ctxt->node && (ctxt->node == ctxt->myDoc->children))
  582.         ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
  583.     /*
  584.      * Check for an Empty Element.
  585.      */
  586.     if ((RAW == '/') && (NXT(1) == '>')) {
  587.         SKIP(2);
  588. if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
  589.     (!ctxt->disableSAX))
  590.     ctxt->sax->endElement(ctxt->userData, name);
  591. oldname = namePop(ctxt);
  592. spacePop(ctxt);
  593. if (oldname != NULL) {
  594. #ifdef DEBUG_STACK
  595.     fprintf(stderr,"Close: popped %sn", oldname);
  596. #endif
  597.     xmlFree(oldname);
  598. }
  599. return;
  600.     }
  601.     if (RAW == '>') {
  602.         NEXT;
  603.     } else {
  604. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  605.     ctxt->sax->error(ctxt->userData,
  606.                      "Couldn't find end of Start Tagn%.30sn",
  607.                      openTag);
  608. ctxt->wellFormed = 0;
  609. ctxt->disableSAX = 1;
  610. ctxt->errNo = XML_ERR_GT_REQUIRED;
  611. /*
  612.  * end of parsing of this node.
  613.  */
  614. nodePop(ctxt);
  615. oldname = namePop(ctxt);
  616. spacePop(ctxt);
  617. if (oldname != NULL) {
  618. #ifdef DEBUG_STACK
  619.     fprintf(stderr,"Close: popped %sn", oldname);
  620. #endif
  621.     xmlFree(oldname);
  622. }
  623. /*
  624.  * Capture end position and add node
  625.  */
  626. if ( ret != NULL && ctxt->record_info ) {
  627.    node_info.end_pos = ctxt->input->consumed +
  628.       (CUR_PTR - ctxt->input->base);
  629.    node_info.end_line = ctxt->input->line;
  630.    node_info.node = ret;
  631.    xmlParserAddNodeInfo(ctxt, &node_info);
  632. }
  633. return;
  634.     }
  635.     /*
  636.      * Parse the content of the element:
  637.      */
  638.     xmlParseContent(ctxt);
  639.     if (!IS_CHAR(RAW)) {
  640. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  641.     ctxt->sax->error(ctxt->userData,
  642.          "Premature end of data in tag %.30sn", openTag);
  643. ctxt->wellFormed = 0;
  644. ctxt->disableSAX = 1;
  645. ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
  646. /*
  647.  * end of parsing of this node.
  648.  */
  649. nodePop(ctxt);
  650. oldname = namePop(ctxt);
  651. spacePop(ctxt);
  652. if (oldname != NULL) {
  653. #ifdef DEBUG_STACK
  654.     fprintf(stderr,"Close: popped %sn", oldname);
  655. #endif
  656.     xmlFree(oldname);
  657. }
  658. return;
  659.     }
  660.     /*
  661.      * parse the end of tag: '</' should be here.
  662.      */
  663.     xmlParseEndTag(ctxt);
  664.     /*
  665.      * Capture end position and add node
  666.      */
  667.     if ( ret != NULL && ctxt->record_info ) {
  668.        node_info.end_pos = ctxt->input->consumed +
  669.                           (CUR_PTR - ctxt->input->base);
  670.        node_info.end_line = ctxt->input->line;
  671.        node_info.node = ret;
  672.        xmlParserAddNodeInfo(ctxt, &node_info);
  673.     }
  674. }
  675. /**
  676.  * xmlParseVersionNum:
  677.  * @ctxt:  an XML parser context
  678.  *
  679.  * parse the XML version value.
  680.  *
  681.  * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
  682.  *
  683.  * Returns the string giving the XML version number, or NULL
  684.  */
  685. xmlChar *
  686. xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
  687.     xmlChar *buf = NULL;
  688.     int len = 0;
  689.     int size = 10;
  690.     xmlChar cur;
  691.     buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
  692.     if (buf == NULL) {
  693. fprintf(stderr, "malloc of %d byte failedn", size);
  694. return(NULL);
  695.     }
  696.     cur = CUR;
  697.     while (((cur >= 'a') && (cur <= 'z')) ||
  698.            ((cur >= 'A') && (cur <= 'Z')) ||
  699.            ((cur >= '0') && (cur <= '9')) ||
  700.            (cur == '_') || (cur == '.') ||
  701.    (cur == ':') || (cur == '-')) {
  702. if (len + 1 >= size) {
  703.     size *= 2;
  704.     buf = xmlRealloc(buf, size * sizeof(xmlChar));
  705.     if (buf == NULL) {
  706. fprintf(stderr, "realloc of %d byte failedn", size);
  707. return(NULL);
  708.     }
  709. }
  710. buf[len++] = cur;
  711. NEXT;
  712. cur=CUR;
  713.     }
  714.     buf[len] = 0;
  715.     return(buf);
  716. }
  717. /**
  718.  * xmlParseVersionInfo:
  719.  * @ctxt:  an XML parser context
  720.  * 
  721.  * parse the XML version.
  722.  *
  723.  * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
  724.  * 
  725.  * [25] Eq ::= S? '=' S?
  726.  *
  727.  * Returns the version string, e.g. "1.0"
  728.  */
  729. xmlChar *
  730. xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
  731.     xmlChar *version = NULL;
  732.     const xmlChar *q;
  733.     if ((RAW == 'v') && (NXT(1) == 'e') &&
  734.         (NXT(2) == 'r') && (NXT(3) == 's') &&
  735. (NXT(4) == 'i') && (NXT(5) == 'o') &&
  736. (NXT(6) == 'n')) {
  737. SKIP(7);
  738. SKIP_BLANKS;
  739. if (RAW != '=') {
  740.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  741.         ctxt->sax->error(ctxt->userData,
  742.                  "xmlParseVersionInfo : expected '='n");
  743.     ctxt->wellFormed = 0;
  744.     ctxt->disableSAX = 1;
  745.     ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
  746.     return(NULL);
  747.         }
  748. NEXT;
  749. SKIP_BLANKS;
  750. if (RAW == '"') {
  751.     NEXT;
  752.     q = CUR_PTR;
  753.     version = xmlParseVersionNum(ctxt);
  754.     if (RAW != '"') {
  755. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  756.     ctxt->sax->error(ctxt->userData, 
  757.                      "String not closedn%.50sn", q);
  758. ctxt->wellFormed = 0;
  759. ctxt->disableSAX = 1;
  760. ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
  761.     } else
  762.         NEXT;
  763. } else if (RAW == '''){
  764.     NEXT;
  765.     q = CUR_PTR;
  766.     version = xmlParseVersionNum(ctxt);
  767.     if (RAW != ''') {
  768. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  769.     ctxt->sax->error(ctxt->userData,
  770.                      "String not closedn%.50sn", q);
  771. ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
  772. ctxt->wellFormed = 0;
  773. ctxt->disableSAX = 1;
  774.     } else
  775.         NEXT;
  776. } else {
  777.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  778.         ctxt->sax->error(ctxt->userData,
  779.       "xmlParseVersionInfo : expected ' or "n");
  780.     ctxt->wellFormed = 0;
  781.     ctxt->disableSAX = 1;
  782.     ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
  783. }
  784.     }
  785.     return(version);
  786. }
  787. /**
  788.  * xmlParseEncName:
  789.  * @ctxt:  an XML parser context
  790.  *
  791.  * parse the XML encoding name
  792.  *
  793.  * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
  794.  *
  795.  * Returns the encoding name value or NULL
  796.  */
  797. xmlChar *
  798. xmlParseEncName(xmlParserCtxtPtr ctxt) {
  799.     xmlChar *buf = NULL;
  800.     int len = 0;
  801.     int size = 10;
  802.     xmlChar cur;
  803.     cur = CUR;
  804.     if (((cur >= 'a') && (cur <= 'z')) ||
  805.         ((cur >= 'A') && (cur <= 'Z'))) {
  806. buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
  807. if (buf == NULL) {
  808.     fprintf(stderr, "malloc of %d byte failedn", size);
  809.     return(NULL);
  810. }
  811. buf[len++] = cur;
  812. NEXT;
  813. cur = CUR;
  814. while (((cur >= 'a') && (cur <= 'z')) ||
  815.        ((cur >= 'A') && (cur <= 'Z')) ||
  816.        ((cur >= '0') && (cur <= '9')) ||
  817.        (cur == '.') || (cur == '_') ||
  818.        (cur == '-')) {
  819.     if (len + 1 >= size) {
  820. size *= 2;
  821. buf = xmlRealloc(buf, size * sizeof(xmlChar));
  822. if (buf == NULL) {
  823.     fprintf(stderr, "realloc of %d byte failedn", size);
  824.     return(NULL);
  825. }
  826.     }
  827.     buf[len++] = cur;
  828.     NEXT;
  829.     cur = CUR;
  830.     if (cur == 0) {
  831.         SHRINK;
  832. GROW;
  833. cur = CUR;
  834.     }
  835.         }
  836. buf[len] = 0;
  837.     } else {
  838. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  839.     ctxt->sax->error(ctxt->userData, "Invalid XML encoding namen");
  840. ctxt->wellFormed = 0;
  841. ctxt->disableSAX = 1;
  842. ctxt->errNo = XML_ERR_ENCODING_NAME;
  843.     }
  844.     return(buf);
  845. }
  846. /**
  847.  * xmlParseEncodingDecl:
  848.  * @ctxt:  an XML parser context
  849.  * 
  850.  * parse the XML encoding declaration
  851.  *
  852.  * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
  853.  *
  854.  * TODO: this should setup the conversion filters.
  855.  *
  856.  * Returns the encoding value or NULL
  857.  */
  858. xmlChar *
  859. xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
  860.     xmlChar *encoding = NULL;
  861.     const xmlChar *q;
  862.     SKIP_BLANKS;
  863.     if ((RAW == 'e') && (NXT(1) == 'n') &&
  864.         (NXT(2) == 'c') && (NXT(3) == 'o') &&
  865. (NXT(4) == 'd') && (NXT(5) == 'i') &&
  866. (NXT(6) == 'n') && (NXT(7) == 'g')) {
  867. SKIP(8);
  868. SKIP_BLANKS;
  869. if (RAW != '=') {
  870.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  871.         ctxt->sax->error(ctxt->userData,
  872.                  "xmlParseEncodingDecl : expected '='n");
  873.     ctxt->wellFormed = 0;
  874.     ctxt->disableSAX = 1;
  875.     ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
  876.     return(NULL);
  877.         }
  878. NEXT;
  879. SKIP_BLANKS;
  880. if (RAW == '"') {
  881.     NEXT;
  882.     q = CUR_PTR;
  883.     encoding = xmlParseEncName(ctxt);
  884.     if (RAW != '"') {
  885. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  886.     ctxt->sax->error(ctxt->userData, 
  887.                      "String not closedn%.50sn", q);
  888. ctxt->wellFormed = 0;
  889. ctxt->disableSAX = 1;
  890. ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
  891.     } else
  892.         NEXT;
  893. } else if (RAW == '''){
  894.     NEXT;
  895.     q = CUR_PTR;
  896.     encoding = xmlParseEncName(ctxt);
  897.     if (RAW != ''') {
  898. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  899.     ctxt->sax->error(ctxt->userData,
  900.                      "String not closedn%.50sn", q);
  901. ctxt->wellFormed = 0;
  902. ctxt->disableSAX = 1;
  903. ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
  904.     } else
  905.         NEXT;
  906. } else if (RAW == '"'){
  907.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  908.         ctxt->sax->error(ctxt->userData,
  909.      "xmlParseEncodingDecl : expected ' or "n");
  910.     ctxt->wellFormed = 0;
  911.     ctxt->disableSAX = 1;
  912.     ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
  913. }
  914.     }
  915.     return(encoding);
  916. }
  917. /**
  918.  * xmlParseSDDecl:
  919.  * @ctxt:  an XML parser context
  920.  *
  921.  * parse the XML standalone declaration
  922.  *
  923.  * [32] SDDecl ::= S 'standalone' Eq
  924.  *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"')) 
  925.  *
  926.  * [ VC: Standalone Document Declaration ]
  927.  * TODO The standalone document declaration must have the value "no"
  928.  * if any external markup declarations contain declarations of:
  929.  *  - attributes with default values, if elements to which these
  930.  *    attributes apply appear in the document without specifications
  931.  *    of values for these attributes, or
  932.  *  - entities (other than amp, lt, gt, apos, quot), if references
  933.  *    to those entities appear in the document, or
  934.  *  - attributes with values subject to normalization, where the
  935.  *    attribute appears in the document with a value which will change
  936.  *    as a result of normalization, or
  937.  *  - element types with element content, if white space occurs directly
  938.  *    within any instance of those types.
  939.  *
  940.  * Returns 1 if standalone, 0 otherwise
  941.  */
  942. int
  943. xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
  944.     int standalone = -1;
  945.     SKIP_BLANKS;
  946.     if ((RAW == 's') && (NXT(1) == 't') &&
  947.         (NXT(2) == 'a') && (NXT(3) == 'n') &&
  948. (NXT(4) == 'd') && (NXT(5) == 'a') &&
  949. (NXT(6) == 'l') && (NXT(7) == 'o') &&
  950. (NXT(8) == 'n') && (NXT(9) == 'e')) {
  951. SKIP(10);
  952.         SKIP_BLANKS;
  953. if (RAW != '=') {
  954.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  955.         ctxt->sax->error(ctxt->userData,
  956.     "XML standalone declaration : expected '='n");
  957.     ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
  958.     ctxt->wellFormed = 0;
  959.     ctxt->disableSAX = 1;
  960.     return(standalone);
  961.         }
  962. NEXT;
  963. SKIP_BLANKS;
  964.         if (RAW == '''){
  965.     NEXT;
  966.     if ((RAW == 'n') && (NXT(1) == 'o')) {
  967.         standalone = 0;
  968.                 SKIP(2);
  969.     } else if ((RAW == 'y') && (NXT(1) == 'e') &&
  970.                (NXT(2) == 's')) {
  971.         standalone = 1;
  972. SKIP(3);
  973.             } else {
  974. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  975.     ctxt->sax->error(ctxt->userData,
  976.                      "standalone accepts only 'yes' or 'no'n");
  977. ctxt->errNo = XML_ERR_STANDALONE_VALUE;
  978. ctxt->wellFormed = 0;
  979. ctxt->disableSAX = 1;
  980.     }
  981.     if (RAW != ''') {
  982. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  983.     ctxt->sax->error(ctxt->userData, "String not closedn");
  984. ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
  985. ctxt->wellFormed = 0;
  986. ctxt->disableSAX = 1;
  987.     } else
  988.         NEXT;
  989. } else if (RAW == '"'){
  990.     NEXT;
  991.     if ((RAW == 'n') && (NXT(1) == 'o')) {
  992.         standalone = 0;
  993. SKIP(2);
  994.     } else if ((RAW == 'y') && (NXT(1) == 'e') &&
  995.                (NXT(2) == 's')) {
  996.         standalone = 1;
  997.                 SKIP(3);
  998.             } else {
  999. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1000.     ctxt->sax->error(ctxt->userData,
  1001.         "standalone accepts only 'yes' or 'no'n");
  1002. ctxt->errNo = XML_ERR_STANDALONE_VALUE;
  1003. ctxt->wellFormed = 0;
  1004. ctxt->disableSAX = 1;
  1005.     }
  1006.     if (RAW != '"') {
  1007. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1008.     ctxt->sax->error(ctxt->userData, "String not closedn");
  1009. ctxt->wellFormed = 0;
  1010. ctxt->disableSAX = 1;
  1011. ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
  1012.     } else
  1013.         NEXT;
  1014. } else {
  1015.             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1016.         ctxt->sax->error(ctxt->userData,
  1017.                  "Standalone value not foundn");
  1018.     ctxt->wellFormed = 0;
  1019.     ctxt->disableSAX = 1;
  1020.     ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
  1021.         }
  1022.     }
  1023.     return(standalone);
  1024. }
  1025. /**
  1026.  * xmlParseXMLDecl:
  1027.  * @ctxt:  an XML parser context
  1028.  * 
  1029.  * parse an XML declaration header
  1030.  *
  1031.  * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
  1032.  */
  1033. void
  1034. xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
  1035.     xmlChar *version;
  1036.     /*
  1037.      * We know that '<?xml' is here.
  1038.      */
  1039.     SKIP(5);
  1040.     if (!IS_BLANK(RAW)) {
  1041. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1042.     ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'n");
  1043. ctxt->errNo = XML_ERR_SPACE_REQUIRED;
  1044. ctxt->wellFormed = 0;
  1045. ctxt->disableSAX = 1;
  1046.     }
  1047.     SKIP_BLANKS;
  1048.     /*
  1049.      * We should have the VersionInfo here.
  1050.      */
  1051.     version = xmlParseVersionInfo(ctxt);
  1052.     if (version == NULL)
  1053. version = xmlCharStrdup(XML_DEFAULT_VERSION);
  1054.     ctxt->version = xmlStrdup(version);
  1055.     xmlFree(version);
  1056.     /*
  1057.      * We may have the encoding declaration
  1058.      */
  1059.     if (!IS_BLANK(RAW)) {
  1060.         if ((RAW == '?') && (NXT(1) == '>')) {
  1061.     SKIP(2);
  1062.     return;
  1063. }
  1064. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1065.     ctxt->sax->error(ctxt->userData, "Blank needed heren");
  1066. ctxt->errNo = XML_ERR_SPACE_REQUIRED;
  1067. ctxt->wellFormed = 0;
  1068. ctxt->disableSAX = 1;
  1069.     }
  1070.     ctxt->input->encoding = xmlParseEncodingDecl(ctxt);
  1071.     /*
  1072.      * We may have the standalone status.
  1073.      */
  1074.     if ((ctxt->input->encoding != NULL) && (!IS_BLANK(RAW))) {
  1075.         if ((RAW == '?') && (NXT(1) == '>')) {
  1076.     SKIP(2);
  1077.     return;
  1078. }
  1079. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1080.     ctxt->sax->error(ctxt->userData, "Blank needed heren");
  1081. ctxt->wellFormed = 0;
  1082. ctxt->disableSAX = 1;
  1083. ctxt->errNo = XML_ERR_SPACE_REQUIRED;
  1084.     }
  1085.     SKIP_BLANKS;
  1086.     ctxt->input->standalone = xmlParseSDDecl(ctxt);
  1087.     SKIP_BLANKS;
  1088.     if ((RAW == '?') && (NXT(1) == '>')) {
  1089.         SKIP(2);
  1090.     } else if (RAW == '>') {
  1091.         /* Deprecated old WD ... */
  1092. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1093.     ctxt->sax->error(ctxt->userData, 
  1094.                      "XML declaration must end-up with '?>'n");
  1095. ctxt->wellFormed = 0;
  1096. ctxt->disableSAX = 1;
  1097. ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
  1098. NEXT;
  1099.     } else {
  1100. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1101.     ctxt->sax->error(ctxt->userData,
  1102.                      "parsing XML declaration: '?>' expectedn");
  1103. ctxt->wellFormed = 0;
  1104. ctxt->disableSAX = 1;
  1105. ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
  1106. MOVETO_ENDTAG(CUR_PTR);
  1107. NEXT;
  1108.     }
  1109. }
  1110. /**
  1111.  * xmlParseMisc:
  1112.  * @ctxt:  an XML parser context
  1113.  * 
  1114.  * parse an XML Misc* optionnal field.
  1115.  *
  1116.  * [27] Misc ::= Comment | PI |  S
  1117.  */
  1118. void
  1119. xmlParseMisc(xmlParserCtxtPtr ctxt) {
  1120.     while (((RAW == '<') && (NXT(1) == '?')) ||
  1121.            ((RAW == '<') && (NXT(1) == '!') &&
  1122.     (NXT(2) == '-') && (NXT(3) == '-')) ||
  1123.            IS_BLANK(CUR)) {
  1124.         if ((RAW == '<') && (NXT(1) == '?')) {
  1125.     xmlParsePI(ctxt);
  1126. } else if (IS_BLANK(CUR)) {
  1127.     NEXT;
  1128. } else
  1129.     xmlParseComment(ctxt);
  1130.     }
  1131. }
  1132. /**
  1133.  * xmlParseDocument:
  1134.  * @ctxt:  an XML parser context
  1135.  * 
  1136.  * parse an XML document (and build a tree if using the standard SAX
  1137.  * interface).
  1138.  *
  1139.  * [1] document ::= prolog element Misc*
  1140.  *
  1141.  * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
  1142.  *
  1143.  * Returns 0, -1 in case of error. the parser context is augmented
  1144.  *                as a result of the parsing.
  1145.  */
  1146. int
  1147. xmlParseDocument(xmlParserCtxtPtr ctxt) {
  1148.     xmlChar start[4];
  1149.     xmlCharEncoding enc;
  1150.     xmlDefaultSAXHandlerInit();
  1151.     GROW;
  1152.     /*
  1153.      * SAX: beginning of the document processing.
  1154.      */
  1155.     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
  1156.         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
  1157.     /* 
  1158.      * Get the 4 first bytes and decode the charset
  1159.      * if enc != XML_CHAR_ENCODING_NONE
  1160.      * plug some encoding conversion routines.
  1161.      */
  1162.     start[0] = RAW;
  1163.     start[1] = NXT(1);
  1164.     start[2] = NXT(2);
  1165.     start[3] = NXT(3);
  1166.     enc = xmlDetectCharEncoding(start, 4);
  1167.     if (enc != XML_CHAR_ENCODING_NONE) {
  1168.         xmlSwitchEncoding(ctxt, enc);
  1169.     }
  1170.     if (CUR == 0) {
  1171. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1172.     ctxt->sax->error(ctxt->userData, "Document is emptyn");
  1173. ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
  1174. ctxt->wellFormed = 0;
  1175. ctxt->disableSAX = 1;
  1176.     }
  1177.     /*
  1178.      * Check for the XMLDecl in the Prolog.
  1179.      */
  1180.     GROW;
  1181.     if ((RAW == '<') && (NXT(1) == '?') &&
  1182.         (NXT(2) == 'x') && (NXT(3) == 'm') &&
  1183. (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
  1184. xmlParseXMLDecl(ctxt);
  1185. ctxt->standalone = ctxt->input->standalone;
  1186. SKIP_BLANKS;
  1187. if ((ctxt->encoding == NULL) && (ctxt->input->encoding != NULL))
  1188.     ctxt->encoding = xmlStrdup(ctxt->input->encoding);
  1189.     } else {
  1190. ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
  1191.     }
  1192.     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
  1193.         ctxt->sax->startDocument(ctxt->userData);
  1194.     /*
  1195.      * The Misc part of the Prolog
  1196.      */
  1197.     GROW;
  1198.     xmlParseMisc(ctxt);
  1199.     /*
  1200.      * Then possibly doc type declaration(s) and more Misc
  1201.      * (doctypedecl Misc*)?
  1202.      */
  1203.     GROW;
  1204.     if ((RAW == '<') && (NXT(1) == '!') &&
  1205. (NXT(2) == 'D') && (NXT(3) == 'O') &&
  1206. (NXT(4) == 'C') && (NXT(5) == 'T') &&
  1207. (NXT(6) == 'Y') && (NXT(7) == 'P') &&
  1208. (NXT(8) == 'E')) {
  1209. ctxt->inSubset = 1;
  1210. xmlParseDocTypeDecl(ctxt);
  1211. if (RAW == '[') {
  1212.     ctxt->instate = XML_PARSER_DTD;
  1213.     xmlParseInternalSubset(ctxt);
  1214. }
  1215. /*
  1216.  * Create and update the external subset.
  1217.  */
  1218. ctxt->inSubset = 2;
  1219. if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
  1220.     (!ctxt->disableSAX))
  1221.     ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
  1222.                               ctxt->extSubSystem, ctxt->extSubURI);
  1223. ctxt->inSubset = 0;
  1224. ctxt->instate = XML_PARSER_PROLOG;
  1225. xmlParseMisc(ctxt);
  1226.     }
  1227.     /*
  1228.      * Time to start parsing the tree itself
  1229.      */
  1230.     GROW;
  1231.     if (RAW != '<') {
  1232. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1233.     ctxt->sax->error(ctxt->userData,
  1234.     "Start tag expected, '<' not foundn");
  1235. ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
  1236. ctxt->wellFormed = 0;
  1237. ctxt->disableSAX = 1;
  1238. ctxt->instate = XML_PARSER_EOF;
  1239.     } else {
  1240. ctxt->instate = XML_PARSER_CONTENT;
  1241. xmlParseElement(ctxt);
  1242. ctxt->instate = XML_PARSER_EPILOG;
  1243. /*
  1244.  * The Misc part at the end
  1245.  */
  1246. xmlParseMisc(ctxt);
  1247. if (RAW != 0) {
  1248.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1249. ctxt->sax->error(ctxt->userData,
  1250.     "Extra content at the end of the documentn");
  1251.     ctxt->wellFormed = 0;
  1252.     ctxt->disableSAX = 1;
  1253.     ctxt->errNo = XML_ERR_DOCUMENT_END;
  1254. }
  1255. ctxt->instate = XML_PARSER_EOF;
  1256.     }
  1257.     /*
  1258.      * SAX: end of the document processing.
  1259.      */
  1260.     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
  1261. (!ctxt->disableSAX))
  1262.         ctxt->sax->endDocument(ctxt->userData);
  1263.     /*
  1264.      * Grab the encoding if it was added on-the-fly
  1265.      */
  1266.     if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
  1267. (ctxt->myDoc->encoding == NULL)) {
  1268. ctxt->myDoc->encoding = ctxt->encoding;
  1269. ctxt->encoding = NULL;
  1270.     }
  1271.     if (! ctxt->wellFormed) return(-1);
  1272.     return(0);
  1273. }
  1274. /************************************************************************
  1275.  * *
  1276.  *  Progressive parsing interfaces *
  1277.  * *
  1278.  ************************************************************************/
  1279. /**
  1280.  * xmlParseLookupSequence:
  1281.  * @ctxt:  an XML parser context
  1282.  * @first:  the first char to lookup
  1283.  * @next:  the next char to lookup or zero
  1284.  * @third:  the next char to lookup or zero
  1285.  *
  1286.  * Try to find if a sequence (first, next, third) or  just (first next) or
  1287.  * (first) is available in the input stream.
  1288.  * This function has a side effect of (possibly) incrementing ctxt->checkIndex
  1289.  * to avoid rescanning sequences of bytes, it DOES change the state of the
  1290.  * parser, do not use liberally.
  1291.  *
  1292.  * Returns the index to the current parsing point if the full sequence
  1293.  *      is available, -1 otherwise.
  1294.  */
  1295. int
  1296. xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
  1297.                        xmlChar next, xmlChar third) {
  1298.     int base, len;
  1299.     xmlParserInputPtr in;
  1300.     const xmlChar *buf;
  1301.     in = ctxt->input;
  1302.     if (in == NULL) return(-1);
  1303.     base = in->cur - in->base;
  1304.     if (base < 0) return(-1);
  1305.     if (ctxt->checkIndex > base)
  1306.         base = ctxt->checkIndex;
  1307.     if (in->buf == NULL) {
  1308. buf = in->base;
  1309. len = in->length;
  1310.     } else {
  1311. buf = in->buf->buffer->content;
  1312. len = in->buf->buffer->use;
  1313.     }
  1314.     /* take into account the sequence length */
  1315.     if (third) len -= 2;
  1316.     else if (next) len --;
  1317.     for (;base < len;base++) {
  1318.         if (buf[base] == first) {
  1319.     if (third != 0) {
  1320. if ((buf[base + 1] != next) ||
  1321.     (buf[base + 2] != third)) continue;
  1322.     } else if (next != 0) {
  1323. if (buf[base + 1] != next) continue;
  1324.     }
  1325.     ctxt->checkIndex = 0;
  1326. #ifdef DEBUG_PUSH
  1327.     if (next == 0)
  1328. fprintf(stderr, "PP: lookup '%c' found at %dn",
  1329. first, base);
  1330.     else if (third == 0)
  1331. fprintf(stderr, "PP: lookup '%c%c' found at %dn",
  1332. first, next, base);
  1333.     else 
  1334. fprintf(stderr, "PP: lookup '%c%c%c' found at %dn",
  1335. first, next, third, base);
  1336. #endif
  1337.     return(base - (in->cur - in->base));
  1338. }
  1339.     }
  1340.     ctxt->checkIndex = base;
  1341. #ifdef DEBUG_PUSH
  1342.     if (next == 0)
  1343. fprintf(stderr, "PP: lookup '%c' failedn", first);
  1344.     else if (third == 0)
  1345. fprintf(stderr, "PP: lookup '%c%c' failedn", first, next);
  1346.     else
  1347. fprintf(stderr, "PP: lookup '%c%c%c' failedn", first, next, third);
  1348. #endif
  1349.     return(-1);
  1350. }
  1351. /**
  1352.  * xmlParseTryOrFinish:
  1353.  * @ctxt:  an XML parser context
  1354.  * @terminate:  last chunk indicator
  1355.  *
  1356.  * Try to progress on parsing
  1357.  *
  1358.  * Returns zero if no parsing was possible
  1359.  */
  1360. int
  1361. xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
  1362.     int ret = 0;
  1363.     int avail;
  1364.     xmlChar cur, next;
  1365. #ifdef DEBUG_PUSH
  1366.     switch (ctxt->instate) {
  1367. case XML_PARSER_EOF:
  1368.     fprintf(stderr, "PP: try EOFn"); break;
  1369. case XML_PARSER_START:
  1370.     fprintf(stderr, "PP: try STARTn"); break;
  1371. case XML_PARSER_MISC:
  1372.     fprintf(stderr, "PP: try MISCn");break;
  1373. case XML_PARSER_COMMENT:
  1374.     fprintf(stderr, "PP: try COMMENTn");break;
  1375. case XML_PARSER_PROLOG:
  1376.     fprintf(stderr, "PP: try PROLOGn");break;
  1377. case XML_PARSER_START_TAG:
  1378.     fprintf(stderr, "PP: try START_TAGn");break;
  1379. case XML_PARSER_CONTENT:
  1380.     fprintf(stderr, "PP: try CONTENTn");break;
  1381. case XML_PARSER_CDATA_SECTION:
  1382.     fprintf(stderr, "PP: try CDATA_SECTIONn");break;
  1383. case XML_PARSER_END_TAG:
  1384.     fprintf(stderr, "PP: try END_TAGn");break;
  1385. case XML_PARSER_ENTITY_DECL:
  1386.     fprintf(stderr, "PP: try ENTITY_DECLn");break;
  1387. case XML_PARSER_ENTITY_VALUE:
  1388.     fprintf(stderr, "PP: try ENTITY_VALUEn");break;
  1389. case XML_PARSER_ATTRIBUTE_VALUE:
  1390.     fprintf(stderr, "PP: try ATTRIBUTE_VALUEn");break;
  1391. case XML_PARSER_DTD:
  1392.     fprintf(stderr, "PP: try DTDn");break;
  1393. case XML_PARSER_EPILOG:
  1394.     fprintf(stderr, "PP: try EPILOGn");break;
  1395. case XML_PARSER_PI:
  1396.     fprintf(stderr, "PP: try PIn");break;
  1397.     }
  1398. #endif
  1399.     while (1) {
  1400. /*
  1401.  * Pop-up of finished entities.
  1402.  */
  1403. while ((RAW == 0) && (ctxt->inputNr > 1))
  1404.     xmlPopInput(ctxt);
  1405. if (ctxt->input ==NULL) break;
  1406. if (ctxt->input->buf == NULL)
  1407.     avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
  1408. else
  1409.     avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
  1410.         if (avail < 1)
  1411.     goto done;
  1412.         switch (ctxt->instate) {
  1413.             case XML_PARSER_EOF:
  1414.         /*
  1415.  * Document parsing is done !
  1416.  */
  1417.         goto done;
  1418.             case XML_PARSER_START:
  1419.         /*
  1420.  * Very first chars read from the document flow.
  1421.  */
  1422. cur = ctxt->input->cur[0];
  1423. if (IS_BLANK(cur)) {
  1424.     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
  1425. ctxt->sax->setDocumentLocator(ctxt->userData,
  1426.       &xmlDefaultSAXLocator);
  1427.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1428. ctxt->sax->error(ctxt->userData,
  1429.     "Extra spaces at the beginning of the document are not allowedn");
  1430.     ctxt->errNo = XML_ERR_DOCUMENT_START;
  1431.     ctxt->wellFormed = 0;
  1432.     ctxt->disableSAX = 1;
  1433.     SKIP_BLANKS;
  1434.     ret++;
  1435.     if (ctxt->input->buf == NULL)
  1436. avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
  1437.     else
  1438. avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
  1439. }
  1440. if (avail < 2)
  1441.     goto done;
  1442. cur = ctxt->input->cur[0];
  1443. next = ctxt->input->cur[1];
  1444. if (cur == 0) {
  1445.     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
  1446. ctxt->sax->setDocumentLocator(ctxt->userData,
  1447.       &xmlDefaultSAXLocator);
  1448.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1449. ctxt->sax->error(ctxt->userData, "Document is emptyn");
  1450.     ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
  1451.     ctxt->wellFormed = 0;
  1452.     ctxt->disableSAX = 1;
  1453.     ctxt->instate = XML_PARSER_EOF;
  1454. #ifdef DEBUG_PUSH
  1455.     fprintf(stderr, "PP: entering EOFn");
  1456. #endif
  1457.     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
  1458. ctxt->sax->endDocument(ctxt->userData);
  1459.     goto done;
  1460. }
  1461.         if ((cur == '<') && (next == '?')) {
  1462.     /* PI or XML decl */
  1463.     if (avail < 5) return(ret);
  1464.     if ((!terminate) &&
  1465.         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
  1466. return(ret);
  1467.     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
  1468. ctxt->sax->setDocumentLocator(ctxt->userData,
  1469.       &xmlDefaultSAXLocator);
  1470.     if ((ctxt->input->cur[2] == 'x') &&
  1471. (ctxt->input->cur[3] == 'm') &&
  1472. (ctxt->input->cur[4] == 'l') &&
  1473. (IS_BLANK(ctxt->input->cur[5]))) {
  1474. ret += 5;
  1475. #ifdef DEBUG_PUSH
  1476. fprintf(stderr, "PP: Parsing XML Decln");
  1477. #endif
  1478. xmlParseXMLDecl(ctxt);
  1479. ctxt->standalone = ctxt->input->standalone;
  1480. if ((ctxt->encoding == NULL) &&
  1481.     (ctxt->input->encoding != NULL))
  1482.     ctxt->encoding = xmlStrdup(ctxt->input->encoding);
  1483. if ((ctxt->sax) && (ctxt->sax->startDocument) &&
  1484.     (!ctxt->disableSAX))
  1485.     ctxt->sax->startDocument(ctxt->userData);
  1486. ctxt->instate = XML_PARSER_MISC;
  1487. #ifdef DEBUG_PUSH
  1488. fprintf(stderr, "PP: entering MISCn");
  1489. #endif
  1490.     } else {
  1491. ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
  1492. if ((ctxt->sax) && (ctxt->sax->startDocument) &&
  1493.     (!ctxt->disableSAX))
  1494.     ctxt->sax->startDocument(ctxt->userData);
  1495. ctxt->instate = XML_PARSER_MISC;
  1496. #ifdef DEBUG_PUSH
  1497. fprintf(stderr, "PP: entering MISCn");
  1498. #endif
  1499.     }
  1500. } else {
  1501.     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
  1502. ctxt->sax->setDocumentLocator(ctxt->userData,
  1503.       &xmlDefaultSAXLocator);
  1504.     ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
  1505.     if ((ctxt->sax) && (ctxt->sax->startDocument) &&
  1506.         (!ctxt->disableSAX))
  1507. ctxt->sax->startDocument(ctxt->userData);
  1508.     ctxt->instate = XML_PARSER_MISC;
  1509. #ifdef DEBUG_PUSH
  1510.     fprintf(stderr, "PP: entering MISCn");
  1511. #endif
  1512. }
  1513. break;
  1514.             case XML_PARSER_MISC:
  1515. SKIP_BLANKS;
  1516. if (ctxt->input->buf == NULL)
  1517.     avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
  1518. else
  1519.     avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
  1520. if (avail < 2)
  1521.     goto done;
  1522. cur = ctxt->input->cur[0];
  1523. next = ctxt->input->cur[1];
  1524.         if ((cur == '<') && (next == '?')) {
  1525.     if ((!terminate) &&
  1526.         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
  1527. goto done;
  1528. #ifdef DEBUG_PUSH
  1529.     fprintf(stderr, "PP: Parsing PIn");
  1530. #endif
  1531.     xmlParsePI(ctxt);
  1532. } else if ((cur == '<') && (next == '!') &&
  1533.     (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
  1534.     if ((!terminate) &&
  1535.         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
  1536. goto done;
  1537. #ifdef DEBUG_PUSH
  1538.     fprintf(stderr, "PP: Parsing Commentn");
  1539. #endif
  1540.     xmlParseComment(ctxt);
  1541.     ctxt->instate = XML_PARSER_MISC;
  1542. } else if ((cur == '<') && (next == '!') &&
  1543.     (ctxt->input->cur[2] == 'D') && (ctxt->input->cur[3] == 'O') &&
  1544.     (ctxt->input->cur[4] == 'C') && (ctxt->input->cur[5] == 'T') &&
  1545.     (ctxt->input->cur[6] == 'Y') && (ctxt->input->cur[7] == 'P') &&
  1546.     (ctxt->input->cur[8] == 'E')) {
  1547.     if ((!terminate) &&
  1548.         (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
  1549. goto done;
  1550. #ifdef DEBUG_PUSH
  1551.     fprintf(stderr, "PP: Parsing internal subsetn");
  1552. #endif
  1553.     ctxt->inSubset = 1;
  1554.     xmlParseDocTypeDecl(ctxt);
  1555.     if (RAW == '[') {
  1556. ctxt->instate = XML_PARSER_DTD;
  1557. #ifdef DEBUG_PUSH
  1558. fprintf(stderr, "PP: entering DTDn");
  1559. #endif
  1560.     } else {
  1561. /*
  1562.  * Create and update the external subset.
  1563.  */
  1564. ctxt->inSubset = 2;
  1565. if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
  1566.     (ctxt->sax->externalSubset != NULL))
  1567.     ctxt->sax->externalSubset(ctxt->userData,
  1568.     ctxt->intSubName, ctxt->extSubSystem,
  1569.     ctxt->extSubURI);
  1570. ctxt->inSubset = 0;
  1571. ctxt->instate = XML_PARSER_PROLOG;
  1572. #ifdef DEBUG_PUSH
  1573. fprintf(stderr, "PP: entering PROLOGn");
  1574. #endif
  1575.     }
  1576. } else if ((cur == '<') && (next == '!') &&
  1577.            (avail < 9)) {
  1578.     goto done;
  1579. } else {
  1580.     ctxt->instate = XML_PARSER_START_TAG;
  1581. #ifdef DEBUG_PUSH
  1582.     fprintf(stderr, "PP: entering START_TAGn");
  1583. #endif
  1584. }
  1585. break;
  1586.             case XML_PARSER_PROLOG:
  1587. SKIP_BLANKS;
  1588. if (ctxt->input->buf == NULL)
  1589.     avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
  1590. else
  1591.     avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
  1592. if (avail < 2) 
  1593.     goto done;
  1594. cur = ctxt->input->cur[0];
  1595. next = ctxt->input->cur[1];
  1596.         if ((cur == '<') && (next == '?')) {
  1597.     if ((!terminate) &&
  1598.         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
  1599. goto done;
  1600. #ifdef DEBUG_PUSH
  1601.     fprintf(stderr, "PP: Parsing PIn");
  1602. #endif
  1603.     xmlParsePI(ctxt);
  1604. } else if ((cur == '<') && (next == '!') &&
  1605.     (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
  1606.     if ((!terminate) &&
  1607.         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
  1608. goto done;
  1609. #ifdef DEBUG_PUSH
  1610.     fprintf(stderr, "PP: Parsing Commentn");
  1611. #endif
  1612.     xmlParseComment(ctxt);
  1613.     ctxt->instate = XML_PARSER_PROLOG;
  1614. } else if ((cur == '<') && (next == '!') &&
  1615.            (avail < 4)) {
  1616.     goto done;
  1617. } else {
  1618.     ctxt->instate = XML_PARSER_START_TAG;
  1619. #ifdef DEBUG_PUSH
  1620.     fprintf(stderr, "PP: entering START_TAGn");
  1621. #endif
  1622. }
  1623. break;
  1624.             case XML_PARSER_EPILOG:
  1625. SKIP_BLANKS;
  1626. if (ctxt->input->buf == NULL)
  1627.     avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
  1628. else
  1629.     avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
  1630. if (avail < 2)
  1631.     goto done;
  1632. cur = ctxt->input->cur[0];
  1633. next = ctxt->input->cur[1];
  1634.         if ((cur == '<') && (next == '?')) {
  1635.     if ((!terminate) &&
  1636.         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
  1637. goto done;
  1638. #ifdef DEBUG_PUSH
  1639.     fprintf(stderr, "PP: Parsing PIn");
  1640. #endif
  1641.     xmlParsePI(ctxt);
  1642.     ctxt->instate = XML_PARSER_EPILOG;
  1643. } else if ((cur == '<') && (next == '!') &&
  1644.     (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
  1645.     if ((!terminate) &&
  1646.         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
  1647. goto done;
  1648. #ifdef DEBUG_PUSH
  1649.     fprintf(stderr, "PP: Parsing Commentn");
  1650. #endif
  1651.     xmlParseComment(ctxt);
  1652.     ctxt->instate = XML_PARSER_EPILOG;
  1653. } else if ((cur == '<') && (next == '!') &&
  1654.            (avail < 4)) {
  1655.     goto done;
  1656. } else {
  1657.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1658. ctxt->sax->error(ctxt->userData,
  1659.     "Extra content at the end of the documentn");
  1660.     ctxt->wellFormed = 0;
  1661.     ctxt->disableSAX = 1;
  1662.     ctxt->errNo = XML_ERR_DOCUMENT_END;
  1663.     ctxt->instate = XML_PARSER_EOF;
  1664. #ifdef DEBUG_PUSH
  1665.     fprintf(stderr, "PP: entering EOFn");
  1666. #endif
  1667.     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
  1668. (!ctxt->disableSAX))
  1669. ctxt->sax->endDocument(ctxt->userData);
  1670.     goto done;
  1671. }
  1672. break;
  1673.             case XML_PARSER_START_TAG: {
  1674.         xmlChar *name, *oldname;
  1675. if ((avail < 2) && (ctxt->inputNr == 1))
  1676.     goto done;
  1677. cur = ctxt->input->cur[0];
  1678.         if (cur != '<') {
  1679.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1680. ctxt->sax->error(ctxt->userData,
  1681. "Start tag expect, '<' not foundn");
  1682.     ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
  1683.     ctxt->wellFormed = 0;
  1684.     ctxt->disableSAX = 1;
  1685.     ctxt->instate = XML_PARSER_EOF;
  1686. #ifdef DEBUG_PUSH
  1687.     fprintf(stderr, "PP: entering EOFn");
  1688. #endif
  1689.     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
  1690. (!ctxt->disableSAX))
  1691. ctxt->sax->endDocument(ctxt->userData);
  1692.     goto done;
  1693. }
  1694. if ((!terminate) &&
  1695.     (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
  1696.     goto done;
  1697. if (ctxt->spaceNr == 0)
  1698.     spacePush(ctxt, -1);
  1699. else
  1700.     spacePush(ctxt, *ctxt->space);
  1701. name = xmlParseStartTag(ctxt);
  1702. if (name == NULL) {
  1703.     spacePop(ctxt);
  1704.     ctxt->instate = XML_PARSER_EOF;
  1705. #ifdef DEBUG_PUSH
  1706.     fprintf(stderr, "PP: entering EOFn");
  1707. #endif
  1708.     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
  1709. (!ctxt->disableSAX))
  1710. ctxt->sax->endDocument(ctxt->userData);
  1711.     goto done;
  1712. }
  1713. namePush(ctxt, xmlStrdup(name));
  1714. /*
  1715.  * [ VC: Root Element Type ]
  1716.  * The Name in the document type declaration must match
  1717.  * the element type of the root element. 
  1718.  */
  1719. if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
  1720.     ctxt->node && (ctxt->node == ctxt->myDoc->children))
  1721.     ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
  1722. /*
  1723.  * Check for an Empty Element.
  1724.  */
  1725. if ((RAW == '/') && (NXT(1) == '>')) {
  1726.     SKIP(2);
  1727.     if ((ctxt->sax != NULL) &&
  1728. (ctxt->sax->endElement != NULL) && (!ctxt->disableSAX))
  1729. ctxt->sax->endElement(ctxt->userData, name);
  1730.     xmlFree(name);
  1731.     oldname = namePop(ctxt);
  1732.     spacePop(ctxt);
  1733.     if (oldname != NULL) {
  1734. #ifdef DEBUG_STACK
  1735. fprintf(stderr,"Close: popped %sn", oldname);
  1736. #endif
  1737. xmlFree(oldname);
  1738.     }
  1739.     if (ctxt->name == NULL) {
  1740. ctxt->instate = XML_PARSER_EPILOG;
  1741. #ifdef DEBUG_PUSH
  1742. fprintf(stderr, "PP: entering EPILOGn");
  1743. #endif
  1744.     } else {
  1745. ctxt->instate = XML_PARSER_CONTENT;
  1746. #ifdef DEBUG_PUSH
  1747. fprintf(stderr, "PP: entering CONTENTn");
  1748. #endif
  1749.     }
  1750.     break;
  1751. }
  1752. if (RAW == '>') {
  1753.     NEXT;
  1754. } else {
  1755.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1756. ctxt->sax->error(ctxt->userData,
  1757.  "Couldn't find end of Start Tag %sn",
  1758.  name);
  1759.     ctxt->wellFormed = 0;
  1760.     ctxt->disableSAX = 1;
  1761.     ctxt->errNo = XML_ERR_GT_REQUIRED;
  1762.     /*
  1763.      * end of parsing of this node.
  1764.      */
  1765.     nodePop(ctxt);
  1766.     oldname = namePop(ctxt);
  1767.     spacePop(ctxt);
  1768.     if (oldname != NULL) {
  1769. #ifdef DEBUG_STACK
  1770. fprintf(stderr,"Close: popped %sn", oldname);
  1771. #endif
  1772. xmlFree(oldname);
  1773.     }
  1774. }
  1775. xmlFree(name);
  1776. ctxt->instate = XML_PARSER_CONTENT;
  1777. #ifdef DEBUG_PUSH
  1778. fprintf(stderr, "PP: entering CONTENTn");
  1779. #endif
  1780.                 break;
  1781.     }
  1782.             case XML_PARSER_CONTENT:
  1783.                 /*
  1784.  * Handle preparsed entities and charRef
  1785.  */
  1786. if (ctxt->token != 0) {
  1787.     xmlChar cur[2] = { 0 , 0 } ;
  1788.     cur[0] = (xmlChar) ctxt->token;
  1789.     if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
  1790. (ctxt->sax->characters != NULL))
  1791. ctxt->sax->characters(ctxt->userData, cur, 1);
  1792.     ctxt->token = 0;
  1793. }
  1794. if ((avail < 2) && (ctxt->inputNr == 1))
  1795.     goto done;
  1796. cur = ctxt->input->cur[0];
  1797. next = ctxt->input->cur[1];
  1798.         if ((cur == '<') && (next == '?')) {
  1799.     if ((!terminate) &&
  1800.         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
  1801. goto done;
  1802. #ifdef DEBUG_PUSH
  1803.     fprintf(stderr, "PP: Parsing PIn");
  1804. #endif
  1805.     xmlParsePI(ctxt);
  1806. } else if ((cur == '<') && (next == '!') &&
  1807.            (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
  1808.     if ((!terminate) &&
  1809.         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
  1810. goto done;
  1811. #ifdef DEBUG_PUSH
  1812.     fprintf(stderr, "PP: Parsing Commentn");
  1813. #endif
  1814.     xmlParseComment(ctxt);
  1815.     ctxt->instate = XML_PARSER_CONTENT;
  1816. } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
  1817.     (ctxt->input->cur[2] == '[') && (NXT(3) == 'C') &&
  1818.     (ctxt->input->cur[4] == 'D') && (NXT(5) == 'A') &&
  1819.     (ctxt->input->cur[6] == 'T') && (NXT(7) == 'A') &&
  1820.     (ctxt->input->cur[8] == '[')) {
  1821.     SKIP(9);
  1822.     ctxt->instate = XML_PARSER_CDATA_SECTION;
  1823. #ifdef DEBUG_PUSH
  1824.     fprintf(stderr, "PP: entering CDATA_SECTIONn");
  1825. #endif
  1826.     break;
  1827. } else if ((cur == '<') && (next == '!') &&
  1828.            (avail < 9)) {
  1829.     goto done;
  1830. } else if ((cur == '<') && (next == '/')) {
  1831.     ctxt->instate = XML_PARSER_END_TAG;
  1832. #ifdef DEBUG_PUSH
  1833.     fprintf(stderr, "PP: entering END_TAGn");
  1834. #endif
  1835.     break;
  1836. } else if (cur == '<') {
  1837.     ctxt->instate = XML_PARSER_START_TAG;
  1838. #ifdef DEBUG_PUSH
  1839.     fprintf(stderr, "PP: entering START_TAGn");
  1840. #endif
  1841.     break;
  1842. } else if (cur == '&') {
  1843.     if ((!terminate) &&
  1844.         (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
  1845. goto done;
  1846. #ifdef DEBUG_PUSH
  1847.     fprintf(stderr, "PP: Parsing Referencen");
  1848. #endif
  1849.     /* TODO: check generation of subtrees if noent !!! */
  1850.     xmlParseReference(ctxt);
  1851. } else {
  1852.     /* TODO Avoid the extra copy, handle directly !!! */
  1853.     /*
  1854.      * Goal of the following test is:
  1855.      *  - minimize calls to the SAX 'character' callback
  1856.      *    when they are mergeable
  1857.      *  - handle an problem for isBlank when we only parse
  1858.      *    a sequence of blank chars and the next one is
  1859.      *    not available to check against '<' presence.
  1860.      *  - tries to homogenize the differences in SAX
  1861.      *    callbacks beween the push and pull versions
  1862.      *    of the parser.
  1863.      */
  1864.     if ((ctxt->inputNr == 1) &&
  1865.         (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
  1866. if ((!terminate) &&
  1867.     (xmlParseLookupSequence(ctxt, '<', 0, 0) < 0))
  1868.     goto done;
  1869.                     }
  1870.     ctxt->checkIndex = 0;
  1871. #ifdef DEBUG_PUSH
  1872.     fprintf(stderr, "PP: Parsing char datan");
  1873. #endif
  1874.     xmlParseCharData(ctxt, 0);
  1875. }
  1876. /*
  1877.  * Pop-up of finished entities.
  1878.  */
  1879. while ((RAW == 0) && (ctxt->inputNr > 1))
  1880.     xmlPopInput(ctxt);
  1881. break;
  1882.             case XML_PARSER_CDATA_SECTION: {
  1883.         /*
  1884.  * The Push mode need to have the SAX callback for 
  1885.  * cdataBlock merge back contiguous callbacks.
  1886.  */
  1887. int base;
  1888. base = xmlParseLookupSequence(ctxt, ']', ']', '>');
  1889. if (base < 0) {
  1890.     if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
  1891. if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
  1892.     if (ctxt->sax->cdataBlock != NULL)
  1893. ctxt->sax->cdataBlock(ctxt->userData, ctxt->input->cur,
  1894.   XML_PARSER_BIG_BUFFER_SIZE);
  1895. }
  1896. SKIP(XML_PARSER_BIG_BUFFER_SIZE);
  1897. ctxt->checkIndex = 0;
  1898.     }
  1899.     goto done;
  1900. } else {
  1901.     if ((ctxt->sax != NULL) && (base > 0) &&
  1902. (!ctxt->disableSAX)) {
  1903. if (ctxt->sax->cdataBlock != NULL)
  1904.     ctxt->sax->cdataBlock(ctxt->userData,
  1905.   ctxt->input->cur, base);
  1906.     }
  1907.     SKIP(base + 3);
  1908.     ctxt->checkIndex = 0;
  1909.     ctxt->instate = XML_PARSER_CONTENT;
  1910. #ifdef DEBUG_PUSH
  1911.     fprintf(stderr, "PP: entering CONTENTn");
  1912. #endif
  1913. }
  1914. break;
  1915.     }
  1916.             case XML_PARSER_END_TAG:
  1917. if (avail < 2)
  1918.     goto done;
  1919. if ((!terminate) &&
  1920.     (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
  1921.     goto done;
  1922. xmlParseEndTag(ctxt);
  1923. if (ctxt->name == NULL) {
  1924.     ctxt->instate = XML_PARSER_EPILOG;
  1925. #ifdef DEBUG_PUSH
  1926.     fprintf(stderr, "PP: entering EPILOGn");
  1927. #endif
  1928. } else {
  1929.     ctxt->instate = XML_PARSER_CONTENT;
  1930. #ifdef DEBUG_PUSH
  1931.     fprintf(stderr, "PP: entering CONTENTn");
  1932. #endif
  1933. }
  1934. break;
  1935.             case XML_PARSER_DTD: {
  1936.         /*
  1937.  * Sorry but progressive parsing of the internal subset
  1938.  * is not expected to be supported. We first check that
  1939.  * the full content of the internal subset is available and
  1940.  * the parsing is launched only at that point.
  1941.  * Internal subset ends up with "']' S? '>'" in an unescaped
  1942.  * section and not in a ']]>' sequence which are conditional
  1943.  * sections (whoever argued to keep that crap in XML deserve
  1944.  * a place in hell !).
  1945.  */
  1946. int base, i;
  1947. xmlChar *buf;
  1948.         xmlChar quote = 0;
  1949. base = ctxt->input->cur - ctxt->input->base;
  1950. if (base < 0) return(0);
  1951. if (ctxt->checkIndex > base)
  1952.     base = ctxt->checkIndex;
  1953. buf = ctxt->input->buf->buffer->content;
  1954. for (;base < ctxt->input->buf->buffer->use;base++) {
  1955.     if (quote != 0) {
  1956.         if (buf[base] == quote)
  1957.     quote = 0;
  1958. continue;    
  1959.     }
  1960.     if (buf[base] == '"') {
  1961.         quote = '"';
  1962. continue;
  1963.     }
  1964.     if (buf[base] == ''') {
  1965.         quote = ''';
  1966. continue;
  1967.     }
  1968.     if (buf[base] == ']') {
  1969.         if (base +1 >= ctxt->input->buf->buffer->use)
  1970.     break;
  1971. if (buf[base + 1] == ']') {
  1972.     /* conditional crap, skip both ']' ! */
  1973.     base++;
  1974.     continue;
  1975. }
  1976.         for (i = 0;base + i < ctxt->input->buf->buffer->use;i++) {
  1977.     if (buf[base + i] == '>')
  1978.         goto found_end_int_subset;
  1979. }
  1980.         break;
  1981.     }
  1982. }
  1983. /*
  1984.  * We didn't found the end of the Internal subset
  1985.  */
  1986. if (quote == 0) 
  1987.     ctxt->checkIndex = base;
  1988. #ifdef DEBUG_PUSH
  1989. if (next == 0)
  1990.     fprintf(stderr, "PP: lookup of int subset end filedn");
  1991. #endif
  1992.         goto done;
  1993. found_end_int_subset:
  1994. xmlParseInternalSubset(ctxt);
  1995. ctxt->inSubset = 2;
  1996. if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
  1997.     (ctxt->sax->externalSubset != NULL))
  1998.     ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
  1999.     ctxt->extSubSystem, ctxt->extSubURI);
  2000. ctxt->inSubset = 0;
  2001. ctxt->instate = XML_PARSER_PROLOG;
  2002. ctxt->checkIndex = 0;
  2003. #ifdef DEBUG_PUSH
  2004. fprintf(stderr, "PP: entering PROLOGn");
  2005. #endif
  2006.                 break;
  2007.     }
  2008.             case XML_PARSER_COMMENT:
  2009. fprintf(stderr, "PP: internal error, state == COMMENTn");
  2010. ctxt->instate = XML_PARSER_CONTENT;
  2011. #ifdef DEBUG_PUSH
  2012. fprintf(stderr, "PP: entering CONTENTn");
  2013. #endif
  2014. break;
  2015.             case XML_PARSER_PI:
  2016. fprintf(stderr, "PP: internal error, state == PIn");
  2017. ctxt->instate = XML_PARSER_CONTENT;
  2018. #ifdef DEBUG_PUSH
  2019. fprintf(stderr, "PP: entering CONTENTn");
  2020. #endif
  2021. break;
  2022.             case XML_PARSER_ENTITY_DECL:
  2023. fprintf(stderr, "PP: internal error, state == ENTITY_DECLn");
  2024. ctxt->instate = XML_PARSER_DTD;
  2025. #ifdef DEBUG_PUSH
  2026. fprintf(stderr, "PP: entering DTDn");
  2027. #endif
  2028. break;
  2029.             case XML_PARSER_ENTITY_VALUE:
  2030. fprintf(stderr, "PP: internal error, state == ENTITY_VALUEn");
  2031. ctxt->instate = XML_PARSER_CONTENT;
  2032. #ifdef DEBUG_PUSH
  2033. fprintf(stderr, "PP: entering DTDn");
  2034. #endif
  2035. break;
  2036.             case XML_PARSER_ATTRIBUTE_VALUE:
  2037. fprintf(stderr, "PP: internal error, state == ATTRIBUTE_VALUEn");
  2038. ctxt->instate = XML_PARSER_START_TAG;
  2039. #ifdef DEBUG_PUSH
  2040. fprintf(stderr, "PP: entering START_TAGn");
  2041. #endif
  2042. break;
  2043.             case XML_PARSER_SYSTEM_LITERAL:
  2044. fprintf(stderr, "PP: internal error, state == SYSTEM_LITERALn");
  2045. ctxt->instate = XML_PARSER_START_TAG;
  2046. #ifdef DEBUG_PUSH
  2047. fprintf(stderr, "PP: entering START_TAGn");
  2048. #endif
  2049. break;
  2050. }
  2051.     }
  2052. done:    
  2053. #ifdef DEBUG_PUSH
  2054.     fprintf(stderr, "PP: done %dn", ret);
  2055. #endif
  2056.     return(ret);
  2057. }
  2058. /**
  2059.  * xmlParseTry:
  2060.  * @ctxt:  an XML parser context
  2061.  *
  2062.  * Try to progress on parsing
  2063.  *
  2064.  * Returns zero if no parsing was possible
  2065.  */
  2066. int
  2067. xmlParseTry(xmlParserCtxtPtr ctxt) {
  2068.     return(xmlParseTryOrFinish(ctxt, 0));
  2069. }
  2070. /**
  2071.  * xmlParseChunk:
  2072.  * @ctxt:  an XML parser context
  2073.  * @chunk:  an char array
  2074.  * @size:  the size in byte of the chunk
  2075.  * @terminate:  last chunk indicator
  2076.  *
  2077.  * Parse a Chunk of memory
  2078.  *
  2079.  * Returns zero if no error, the xmlParserErrors otherwise.
  2080.  */
  2081. int
  2082. xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
  2083.               int terminate) {
  2084.     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
  2085.         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
  2086. int base = ctxt->input->base - ctxt->input->buf->buffer->content;
  2087. int cur = ctxt->input->cur - ctxt->input->base;
  2088. xmlParserInputBufferPush(ctxt->input->buf, size, chunk);       
  2089. ctxt->input->base = ctxt->input->buf->buffer->content + base;
  2090. ctxt->input->cur = ctxt->input->base + cur;
  2091. #ifdef DEBUG_PUSH
  2092. fprintf(stderr, "PP: pushed %dn", size);
  2093. #endif
  2094. if ((terminate) || (ctxt->input->buf->buffer->use > 80))
  2095.     xmlParseTryOrFinish(ctxt, terminate);
  2096.     } else if (ctxt->instate != XML_PARSER_EOF)
  2097.         xmlParseTryOrFinish(ctxt, terminate);
  2098.     if (terminate) {
  2099. /*
  2100.  * Grab the encoding if it was added on-the-fly
  2101.  */
  2102. if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
  2103.     (ctxt->myDoc->encoding == NULL)) {
  2104.     ctxt->myDoc->encoding = ctxt->encoding;
  2105.     ctxt->encoding = NULL;
  2106. }
  2107. /*
  2108.  * Check for termination
  2109.  */
  2110. if ((ctxt->instate != XML_PARSER_EOF) &&
  2111.     (ctxt->instate != XML_PARSER_EPILOG)) {
  2112.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2113. ctxt->sax->error(ctxt->userData,
  2114.     "Extra content at the end of the documentn");
  2115.     ctxt->wellFormed = 0;
  2116.     ctxt->disableSAX = 1;
  2117.     ctxt->errNo = XML_ERR_DOCUMENT_END;
  2118. if (ctxt->instate != XML_PARSER_EOF) {
  2119.     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
  2120. (!ctxt->disableSAX))
  2121. ctxt->sax->endDocument(ctxt->userData);
  2122. }
  2123. ctxt->instate = XML_PARSER_EOF;
  2124.     }
  2125.     return((xmlParserErrors) ctxt->errNo);       
  2126. }
  2127. /************************************************************************
  2128.  * *
  2129.  *  I/O front end functions to the parser *
  2130.  * *
  2131.  ************************************************************************/
  2132. /**
  2133.  * xmlCreatePushParserCtxt:
  2134.  * @sax:  a SAX handler
  2135.  * @user_data:  The user data returned on SAX callbacks
  2136.  * @chunk:  a pointer to an array of chars
  2137.  * @size:  number of chars in the array
  2138.  * @filename:  an optional file name or URI
  2139.  *
  2140.  * Create a parser context for using the XML parser in push mode
  2141.  * To allow content encoding detection, @size should be >= 4
  2142.  * The value of @filename is used for fetching external entities
  2143.  * and error/warning reports.
  2144.  *
  2145.  * Returns the new parser context or NULL
  2146.  */
  2147. xmlParserCtxtPtr
  2148. xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, 
  2149.                         const char *chunk, int size, const char *filename) {
  2150.     xmlParserCtxtPtr ctxt;
  2151.     xmlParserInputPtr inputStream;
  2152.     xmlParserInputBufferPtr buf;
  2153.     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
  2154.     /*
  2155.      * plug some encoding conversion routines
  2156.      */
  2157.     if ((chunk != NULL) && (size >= 4))
  2158. enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
  2159.     buf = xmlAllocParserInputBuffer(enc);
  2160.     if (buf == NULL) return(NULL);
  2161.     ctxt = xmlNewParserCtxt();
  2162.     if (ctxt == NULL) {
  2163. xmlFree(buf);
  2164. return(NULL);
  2165.     }
  2166.     if (sax != NULL) {
  2167. if (ctxt->sax != &xmlDefaultSAXHandler)
  2168.     xmlFree(ctxt->sax);
  2169. ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
  2170. if (ctxt->sax == NULL) {
  2171.     xmlFree(buf);
  2172.     xmlFree(ctxt);
  2173.     return(NULL);
  2174. }
  2175. memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
  2176. if (user_data != NULL)
  2177.     ctxt->userData = user_data;
  2178.     }
  2179.     if (filename == NULL) {
  2180. ctxt->directory = NULL;
  2181.     } else {
  2182.         ctxt->directory = xmlParserGetDirectory(filename);
  2183.     }
  2184.     inputStream = xmlNewInputStream(ctxt);
  2185.     if (inputStream == NULL) {
  2186. xmlFreeParserCtxt(ctxt);
  2187. return(NULL);
  2188.     }
  2189.     if (filename == NULL)
  2190. inputStream->filename = NULL;
  2191.     else
  2192. inputStream->filename = xmlMemStrdup(filename);
  2193.     inputStream->buf = buf;
  2194.     inputStream->base = inputStream->buf->buffer->content;
  2195.     inputStream->cur = inputStream->buf->buffer->content;
  2196.     if (enc != XML_CHAR_ENCODING_NONE) {
  2197.         xmlSwitchEncoding(ctxt, enc);
  2198.     }
  2199.     inputPush(ctxt, inputStream);
  2200.     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
  2201.         (ctxt->input->buf != NULL))  {       
  2202. xmlParserInputBufferPush(ctxt->input->buf, size, chunk);       
  2203. #ifdef DEBUG_PUSH
  2204. fprintf(stderr, "PP: pushed %dn", size);
  2205. #endif
  2206.     }
  2207.     return(ctxt);
  2208. }
  2209. /**
  2210.  * xmlCreateIOParserCtxt:
  2211.  * @sax:  a SAX handler
  2212.  * @user_data:  The user data returned on SAX callbacks
  2213.  * @ioread:  an I/O read function
  2214.  * @ioclose:  an I/O close function
  2215.  * @ioctx:  an I/O handler
  2216.  * @enc:  the charset encoding if known
  2217.  *
  2218.  * Create a parser context for using the XML parser with an existing
  2219.  * I/O stream
  2220.  *
  2221.  * Returns the new parser context or NULL
  2222.  */
  2223. xmlParserCtxtPtr
  2224. xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
  2225. xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
  2226. void *ioctx, xmlCharEncoding enc) {
  2227.     xmlParserCtxtPtr ctxt;
  2228.     xmlParserInputPtr inputStream;
  2229.     xmlParserInputBufferPtr buf;
  2230.     buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
  2231.     if (buf == NULL) return(NULL);
  2232.     ctxt = xmlNewParserCtxt();
  2233.     if (ctxt == NULL) {
  2234. xmlFree(buf);
  2235. return(NULL);
  2236.     }
  2237.     if (sax != NULL) {
  2238. if (ctxt->sax != &xmlDefaultSAXHandler)
  2239.     xmlFree(ctxt->sax);
  2240. ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
  2241. if (ctxt->sax == NULL) {
  2242.     xmlFree(buf);
  2243.     xmlFree(ctxt);
  2244.     return(NULL);
  2245. }
  2246. memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
  2247. if (user_data != NULL)
  2248.     ctxt->userData = user_data;
  2249.     }
  2250.     inputStream = xmlNewIOInputStream(ctxt, buf, enc);
  2251.     if (inputStream == NULL) {
  2252. xmlFreeParserCtxt(ctxt);
  2253. return(NULL);
  2254.     }
  2255.     inputPush(ctxt, inputStream);
  2256.     return(ctxt);
  2257. }
  2258. /**
  2259.  * xmlCreateDocParserCtxt:
  2260.  * @cur:  a pointer to an array of xmlChar
  2261.  *
  2262.  * Create a parser context for an XML in-memory document.
  2263.  *
  2264.  * Returns the new parser context or NULL
  2265.  */
  2266. xmlParserCtxtPtr
  2267. xmlCreateDocParserCtxt(xmlChar *cur) {
  2268.     xmlParserCtxtPtr ctxt;
  2269.     xmlParserInputPtr input;
  2270.     ctxt = xmlNewParserCtxt();
  2271.     if (ctxt == NULL) {
  2272. return(NULL);
  2273.     }
  2274.     input = xmlNewInputStream(ctxt);
  2275.     if (input == NULL) {
  2276. xmlFreeParserCtxt(ctxt);
  2277. return(NULL);
  2278.     }
  2279.     input->base = cur;
  2280.     input->cur = cur;
  2281.     inputPush(ctxt, input);
  2282.     return(ctxt);
  2283. }
  2284. /**
  2285.  * xmlSAXParseDoc:
  2286.  * @sax:  the SAX handler block
  2287.  * @cur:  a pointer to an array of xmlChar
  2288.  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
  2289.  *             documents
  2290.  *
  2291.  * parse an XML in-memory document and build a tree.
  2292.  * It use the given SAX function block to handle the parsing callback.
  2293.  * If sax is NULL, fallback to the default DOM tree building routines.
  2294.  * 
  2295.  * Returns the resulting document tree
  2296.  */
  2297. xmlDocPtr
  2298. xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
  2299.     xmlDocPtr ret;
  2300.     xmlParserCtxtPtr ctxt;
  2301.     if (cur == NULL) return(NULL);
  2302.     ctxt = xmlCreateDocParserCtxt(cur);
  2303.     if (ctxt == NULL) return(NULL);
  2304.     if (sax != NULL) { 
  2305.         ctxt->sax = sax;
  2306.         ctxt->userData = NULL;
  2307.     }
  2308.     xmlParseDocument(ctxt);
  2309.     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
  2310.     else {
  2311.        ret = NULL;
  2312.        xmlFreeDoc(ctxt->myDoc);
  2313.        ctxt->myDoc = NULL;
  2314.     }
  2315.     if (sax != NULL) 
  2316. ctxt->sax = NULL;
  2317.     xmlFreeParserCtxt(ctxt);
  2318.     
  2319.     return(ret);
  2320. }
  2321. /**
  2322.  * xmlParseDoc:
  2323.  * @cur:  a pointer to an array of xmlChar
  2324.  *
  2325.  * parse an XML in-memory document and build a tree.
  2326.  * 
  2327.  * Returns the resulting document tree
  2328.  */
  2329. xmlDocPtr
  2330. xmlParseDoc(xmlChar *cur) {
  2331.     return(xmlSAXParseDoc(NULL, cur, 0));
  2332. }
  2333. /**
  2334.  * xmlSAXParseDTD:
  2335.  * @sax:  the SAX handler block
  2336.  * @ExternalID:  a NAME* containing the External ID of the DTD
  2337.  * @SystemID:  a NAME* containing the URL to the DTD
  2338.  *
  2339.  * Load and parse an external subset.
  2340.  * 
  2341.  * Returns the resulting xmlDtdPtr or NULL in case of error.
  2342.  */
  2343. xmlDtdPtr
  2344. xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
  2345.                           const xmlChar *SystemID) {
  2346.     xmlDtdPtr ret = NULL;
  2347.     xmlParserCtxtPtr ctxt;
  2348.     xmlParserInputPtr input = NULL;
  2349.     xmlCharEncoding enc;
  2350.     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
  2351.     ctxt = xmlNewParserCtxt();
  2352.     if (ctxt == NULL) {
  2353. return(NULL);
  2354.     }
  2355.     /*
  2356.      * Set-up the SAX context
  2357.      */
  2358.     if (ctxt == NULL) return(NULL);
  2359.     if (sax != NULL) { 
  2360. if (ctxt->sax != NULL)
  2361.     xmlFree(ctxt->sax);
  2362.         ctxt->sax = sax;
  2363.         ctxt->userData = NULL;
  2364.     }
  2365.     /*
  2366.      * Ask the Entity resolver to load the damn thing
  2367.      */
  2368.     if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
  2369. input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
  2370.     if (input == NULL) {
  2371.         if (sax != NULL) ctxt->sax = NULL;
  2372. xmlFreeParserCtxt(ctxt);
  2373. return(NULL);
  2374.     }
  2375.     /*
  2376.      * plug some encoding conversion routines here.
  2377.      */
  2378.     xmlPushInput(ctxt, input);
  2379.     enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
  2380.     xmlSwitchEncoding(ctxt, enc);
  2381.     if (input->filename == NULL)
  2382. input->filename = (char *) xmlStrdup(SystemID);
  2383.     input->line = 1;
  2384.     input->col = 1;
  2385.     input->base = ctxt->input->cur;
  2386.     input->cur = ctxt->input->cur;
  2387.     input->free = NULL;
  2388.     /*
  2389.      * let's parse that entity knowing it's an external subset.
  2390.      */
  2391.     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
  2392.     if (ctxt->myDoc != NULL) {
  2393. if (ctxt->wellFormed) {
  2394.     ret = ctxt->myDoc->intSubset;
  2395.     ctxt->myDoc->intSubset = NULL;
  2396. } else {
  2397.     ret = NULL;
  2398. }
  2399.         xmlFreeDoc(ctxt->myDoc);
  2400.         ctxt->myDoc = NULL;
  2401.     }
  2402.     if (sax != NULL) ctxt->sax = NULL;
  2403.     xmlFreeParserCtxt(ctxt);
  2404.     
  2405.     return(ret);
  2406. }
  2407. /**
  2408.  * xmlParseDTD:
  2409.  * @ExternalID:  a NAME* containing the External ID of the DTD
  2410.  * @SystemID:  a NAME* containing the URL to the DTD
  2411.  *
  2412.  * Load and parse an external subset.
  2413.  * 
  2414.  * Returns the resulting xmlDtdPtr or NULL in case of error.
  2415.  */
  2416. xmlDtdPtr
  2417. xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
  2418.     return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
  2419. }
  2420. /**
  2421.  * xmlSAXParseBalancedChunk:
  2422.  * @ctx:  an XML parser context (possibly NULL)
  2423.  * @sax:  the SAX handler bloc (possibly NULL)
  2424.  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  2425.  * @input:  a parser input stream
  2426.  * @enc:  the encoding
  2427.  *
  2428.  * Parse a well-balanced chunk of an XML document
  2429.  * The user has to provide SAX callback block whose routines will be
  2430.  * called by the parser
  2431.  * The allowed sequence for the Well Balanced Chunk is the one defined by
  2432.  * the content production in the XML grammar:
  2433.  *
  2434.  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
  2435.  *
  2436.  * Returns 0 if the chunk is well balanced, -1 in case of args problem and
  2437.  *    the error code otherwise
  2438.  */
  2439. int
  2440. xmlSAXParseBalancedChunk(xmlParserCtxtPtr ctx, xmlSAXHandlerPtr sax,
  2441.                          void *user_data, xmlParserInputPtr input,
  2442.  xmlCharEncoding enc) {
  2443.     xmlParserCtxtPtr ctxt;
  2444.     int ret;
  2445.     if (input == NULL) return(-1);
  2446.     if (ctx != NULL)
  2447.         ctxt = ctx;
  2448.     else {
  2449. ctxt = xmlNewParserCtxt();
  2450. if (ctxt == NULL)
  2451.     return(-1);
  2452.         if (sax == NULL)
  2453.     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
  2454.     }
  2455.     /*
  2456.      * Set-up the SAX context
  2457.      */
  2458.     if (sax != NULL) {
  2459. if (ctxt->sax != NULL)
  2460.     xmlFree(ctxt->sax);
  2461. ctxt->sax = sax;
  2462. ctxt->userData = user_data;
  2463.     }
  2464.     /*
  2465.      * plug some encoding conversion routines here.
  2466.      */
  2467.     xmlPushInput(ctxt, input);
  2468.     if (enc != XML_CHAR_ENCODING_NONE)
  2469. xmlSwitchEncoding(ctxt, enc);
  2470.     /*
  2471.      * let's parse that entity knowing it's an external subset.
  2472.      */
  2473.     xmlParseContent(ctxt);
  2474.     ret = ctxt->errNo;
  2475.     if (ctx == NULL) {
  2476. if (sax != NULL) 
  2477.     ctxt->sax = NULL;
  2478. else
  2479.     xmlFreeDoc(ctxt->myDoc);
  2480. xmlFreeParserCtxt(ctxt);
  2481.     }
  2482.     return(ret);
  2483. }
  2484. /**
  2485.  * xmlParseExternalEntity:
  2486.  * @doc:  the document the chunk pertains to
  2487.  * @sax:  the SAX handler bloc (possibly NULL)
  2488.  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  2489.  * @depth:  Used for loop detection, use 0
  2490.  * @URL:  the URL for the entity to load
  2491.  * @ID:  the System ID for the entity to load
  2492.  * @list:  the return value for the set of parsed nodes
  2493.  *
  2494.  * Parse an external general entity
  2495.  * An external general parsed entity is well-formed if it matches the
  2496.  * production labeled extParsedEnt.
  2497.  *
  2498.  * [78] extParsedEnt ::= TextDecl? content
  2499.  *
  2500.  * Returns 0 if the entity is well formed, -1 in case of args problem and
  2501.  *    the parser error code otherwise
  2502.  */
  2503. int
  2504. xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
  2505.   int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *list) {
  2506.     xmlParserCtxtPtr ctxt;
  2507.     xmlDocPtr newDoc;
  2508.     xmlSAXHandlerPtr oldsax = NULL;
  2509.     int ret = 0;
  2510.     if (depth > 40) {
  2511. return(XML_ERR_ENTITY_LOOP);
  2512.     }
  2513.     if (list != NULL)
  2514.         *list = NULL;
  2515.     if ((URL == NULL) && (ID == NULL))
  2516. return(-1);
  2517.     ctxt = xmlCreateEntityParserCtxt(URL, ID, doc->URL);
  2518.     if (ctxt == NULL) return(-1);
  2519.     ctxt->userData = ctxt;
  2520.     if (sax != NULL) {
  2521. oldsax = ctxt->sax;
  2522.         ctxt->sax = sax;
  2523. if (user_data != NULL)
  2524.     ctxt->userData = user_data;
  2525.     }
  2526.     newDoc = xmlNewDoc(BAD_CAST "1.0");
  2527.     if (newDoc == NULL) {
  2528. xmlFreeParserCtxt(ctxt);
  2529. return(-1);
  2530.     }
  2531.     if (doc != NULL) {
  2532. newDoc->intSubset = doc->intSubset;
  2533. newDoc->extSubset = doc->extSubset;
  2534.     }
  2535.     if (doc->URL != NULL) {
  2536. newDoc->URL = xmlStrdup(doc->URL);
  2537.     }
  2538.     newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
  2539.     if (newDoc->children == NULL) {
  2540. if (sax != NULL)
  2541.     ctxt->sax = oldsax;
  2542. xmlFreeParserCtxt(ctxt);
  2543. newDoc->intSubset = NULL;
  2544. newDoc->extSubset = NULL;
  2545.         xmlFreeDoc(newDoc);
  2546. return(-1);
  2547.     }
  2548.     nodePush(ctxt, newDoc->children);
  2549.     if (doc == NULL) {
  2550. ctxt->myDoc = newDoc;
  2551.     } else {
  2552. ctxt->myDoc = doc;
  2553. newDoc->children->doc = doc;
  2554.     }
  2555.     /*
  2556.      * Parse a possible text declaration first
  2557.      */
  2558.     GROW;
  2559.     if ((RAW == '<') && (NXT(1) == '?') &&
  2560. (NXT(2) == 'x') && (NXT(3) == 'm') &&
  2561. (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
  2562. xmlParseTextDecl(ctxt);
  2563.     }
  2564.     /*
  2565.      * Doing validity checking on chunk doesn't make sense
  2566.      */
  2567.     ctxt->instate = XML_PARSER_CONTENT;
  2568.     ctxt->validate = 0;
  2569.     ctxt->depth = depth;
  2570.     xmlParseContent(ctxt);
  2571.    
  2572.     if ((RAW == '<') && (NXT(1) == '/')) {
  2573. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2574.     ctxt->sax->error(ctxt->userData,
  2575. "chunk is not well balancedn");
  2576. ctxt->wellFormed = 0;
  2577. ctxt->disableSAX = 1;
  2578. ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
  2579.     } else if (RAW != 0) {
  2580. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2581.     ctxt->sax->error(ctxt->userData,
  2582. "extra content at the end of well balanced chunkn");
  2583. ctxt->wellFormed = 0;
  2584. ctxt->disableSAX = 1;
  2585. ctxt->errNo = XML_ERR_EXTRA_CONTENT;
  2586.     }
  2587.     if (ctxt->node != newDoc->children) {
  2588. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2589.     ctxt->sax->error(ctxt->userData,
  2590. "chunk is not well balancedn");
  2591. ctxt->wellFormed = 0;
  2592. ctxt->disableSAX = 1;
  2593. ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
  2594.     }
  2595.     if (!ctxt->wellFormed) {
  2596.         if (ctxt->errNo == 0)
  2597.     ret = 1;
  2598. else
  2599.     ret = ctxt->errNo;
  2600.     } else {
  2601. if (list != NULL) {
  2602.     xmlNodePtr cur;
  2603.     /*
  2604.      * Return the newly created nodeset after unlinking it from
  2605.      * they pseudo parent.
  2606.      */
  2607.     cur = newDoc->children->children;
  2608.     *list = cur;
  2609.     while (cur != NULL) {
  2610. cur->parent = NULL;
  2611. cur = cur->next;
  2612.     }
  2613.             newDoc->children->children = NULL;
  2614. }
  2615. ret = 0;
  2616.     }
  2617.     if (sax != NULL) 
  2618. ctxt->sax = oldsax;
  2619.     xmlFreeParserCtxt(ctxt);
  2620.     newDoc->intSubset = NULL;
  2621.     newDoc->extSubset = NULL;
  2622.     xmlFreeDoc(newDoc);
  2623.     
  2624.     return(ret);
  2625. }
  2626. /**
  2627.  * xmlParseBalancedChunk:
  2628.  * @doc:  the document the chunk pertains to
  2629.  * @sax:  the SAX handler bloc (possibly NULL)
  2630.  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  2631.  * @depth:  Used for loop detection, use 0
  2632.  * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
  2633.  * @list:  the return value for the set of parsed nodes
  2634.  *
  2635.  * Parse a well-balanced chunk of an XML document
  2636.  * called by the parser
  2637.  * The allowed sequence for the Well Balanced Chunk is the one defined by
  2638.  * the content production in the XML grammar:
  2639.  *
  2640.  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
  2641.  *
  2642.  * Returns 0 if the chunk is well balanced, -1 in case of args problem and
  2643.  *    the parser error code otherwise
  2644.  */
  2645. int
  2646. xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
  2647.      void *user_data, int depth, const xmlChar *string, xmlNodePtr *list) {
  2648.     xmlParserCtxtPtr ctxt;
  2649.     xmlDocPtr newDoc;
  2650.     xmlSAXHandlerPtr oldsax = NULL;
  2651.     int size;
  2652.     int ret = 0;
  2653.     if (depth > 40) {
  2654. return(XML_ERR_ENTITY_LOOP);
  2655.     }
  2656.     if (list != NULL)
  2657.         *list = NULL;
  2658.     if (string == NULL)
  2659.         return(-1);
  2660.     size = xmlStrlen(string);
  2661.     ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
  2662.     if (ctxt == NULL) return(-1);
  2663.     ctxt->userData = ctxt;
  2664.     if (sax != NULL) {
  2665. oldsax = ctxt->sax;
  2666.         ctxt->sax = sax;
  2667. if (user_data != NULL)
  2668.     ctxt->userData = user_data;
  2669.     }
  2670.     newDoc = xmlNewDoc(BAD_CAST "1.0");
  2671.     if (newDoc == NULL) {
  2672. xmlFreeParserCtxt(ctxt);
  2673. return(-1);
  2674.     }
  2675.     if (doc != NULL) {
  2676. newDoc->intSubset = doc->intSubset;
  2677. newDoc->extSubset = doc->extSubset;
  2678.     }
  2679.     newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
  2680.     if (newDoc->children == NULL) {
  2681. if (sax != NULL)
  2682.     ctxt->sax = oldsax;
  2683. xmlFreeParserCtxt(ctxt);
  2684. newDoc->intSubset = NULL;
  2685. newDoc->extSubset = NULL;
  2686.         xmlFreeDoc(newDoc);
  2687. return(-1);
  2688.     }
  2689.     nodePush(ctxt, newDoc->children);
  2690.     if (doc == NULL) {
  2691. ctxt->myDoc = newDoc;
  2692.     } else {
  2693. ctxt->myDoc = doc;
  2694. newDoc->children->doc = doc;
  2695.     }
  2696.     ctxt->instate = XML_PARSER_CONTENT;
  2697.     ctxt->depth = depth;
  2698.     /*
  2699.      * Doing validity checking on chunk doesn't make sense
  2700.      */
  2701.     ctxt->validate = 0;
  2702.     xmlParseContent(ctxt);
  2703.    
  2704.     if ((RAW == '<') && (NXT(1) == '/')) {
  2705. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2706.     ctxt->sax->error(ctxt->userData,
  2707. "chunk is not well balancedn");
  2708. ctxt->wellFormed = 0;
  2709. ctxt->disableSAX = 1;
  2710. ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
  2711.     } else if (RAW != 0) {
  2712. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2713.     ctxt->sax->error(ctxt->userData,
  2714. "extra content at the end of well balanced chunkn");
  2715. ctxt->wellFormed = 0;
  2716. ctxt->disableSAX = 1;
  2717. ctxt->errNo = XML_ERR_EXTRA_CONTENT;
  2718.     }
  2719.     if (ctxt->node != newDoc->children) {
  2720. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  2721.     ctxt->sax->error(ctxt->userData,
  2722. "chunk is not well balancedn");
  2723. ctxt->wellFormed = 0;
  2724. ctxt->disableSAX = 1;
  2725. ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
  2726.     }
  2727.     if (!ctxt->wellFormed) {
  2728.         if (ctxt->errNo == 0)
  2729.     ret = 1;
  2730. else
  2731.     ret = ctxt->errNo;
  2732.     } else {
  2733. if (list != NULL) {
  2734.     xmlNodePtr cur;
  2735.     /*
  2736.      * Return the newly created nodeset after unlinking it from
  2737.      * they pseudo parent.
  2738.      */
  2739.     cur = newDoc->children->children;
  2740.     *list = cur;
  2741.     while (cur != NULL) {
  2742. cur->parent = NULL;
  2743. cur = cur->next;
  2744.     }
  2745.             newDoc->children->children = NULL;
  2746. }
  2747. ret = 0;
  2748.     }
  2749.     if (sax != NULL) 
  2750. ctxt->sax = oldsax;
  2751.     xmlFreeParserCtxt(ctxt);
  2752.     newDoc->intSubset = NULL;
  2753.     newDoc->extSubset = NULL;
  2754.     xmlFreeDoc(newDoc);
  2755.     
  2756.     return(ret);
  2757. }
  2758. /**
  2759.  * xmlParseBalancedChunkFile:
  2760.  * @doc:  the document the chunk pertains to
  2761.  *
  2762.  * Parse a well-balanced chunk of an XML document contained in a file
  2763.  * 
  2764.  * Returns the resulting list of nodes resulting from the parsing,
  2765.  *     they are not added to @node
  2766.  */
  2767. xmlNodePtr
  2768. xmlParseBalancedChunkFile(xmlDocPtr doc, xmlNodePtr node) {
  2769.     /* TODO !!! */
  2770.     return(NULL);
  2771. }
  2772. /**
  2773.  * xmlRecoverDoc:
  2774.  * @cur:  a pointer to an array of xmlChar
  2775.  *
  2776.  * parse an XML in-memory document and build a tree.
  2777.  * In the case the document is not Well Formed, a tree is built anyway
  2778.  * 
  2779.  * Returns the resulting document tree
  2780.  */
  2781. xmlDocPtr
  2782. xmlRecoverDoc(xmlChar *cur) {
  2783.     return(xmlSAXParseDoc(NULL, cur, 1));
  2784. }
  2785. /**
  2786.  * xmlCreateEntityParserCtxt:
  2787.  * @URL:  the entity URL
  2788.  * @ID:  the entity PUBLIC ID
  2789.  * @base:  a posible base for the target URI
  2790.  *
  2791.  * Create a parser context for an external entity
  2792.  * Automatic support for ZLIB/Compress compressed document is provided
  2793.  * by default if found at compile-time.
  2794.  *
  2795.  * Returns the new parser context or NULL
  2796.  */
  2797. xmlParserCtxtPtr
  2798. xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
  2799.                   const xmlChar *base) {
  2800.     xmlParserCtxtPtr ctxt;
  2801.     xmlParserInputPtr inputStream;
  2802.     char *directory = NULL;
  2803.     ctxt = xmlNewParserCtxt();
  2804.     if (ctxt == NULL) {
  2805. return(NULL);
  2806.     }
  2807.     inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
  2808.     if (inputStream == NULL) {
  2809. xmlFreeParserCtxt(ctxt);
  2810. return(NULL);
  2811.     }
  2812.     inputPush(ctxt, inputStream);
  2813.     if ((ctxt->directory == NULL) && (directory == NULL))
  2814.         directory = xmlParserGetDirectory((char *)URL);
  2815.     if ((ctxt->directory == NULL) && (directory != NULL))
  2816.         ctxt->directory = directory;
  2817.     return(ctxt);
  2818. }
  2819. /**
  2820.  * xmlCreateFileParserCtxt:
  2821.  * @filename:  the filename
  2822.  *
  2823.  * Create a parser context for a file content. 
  2824.  * Automatic support for ZLIB/Compress compressed document is provided
  2825.  * by default if found at compile-time.
  2826.  *
  2827.  * Returns the new parser context or NULL
  2828.  */
  2829. xmlParserCtxtPtr
  2830. xmlCreateFileParserCtxt(const char *filename)
  2831. {
  2832.     xmlParserCtxtPtr ctxt;
  2833.     xmlParserInputPtr inputStream;
  2834.     xmlParserInputBufferPtr buf;
  2835.     char *directory = NULL;
  2836.     buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
  2837.     if (buf == NULL) return(NULL);
  2838.     ctxt = xmlNewParserCtxt();
  2839.     if (ctxt == NULL) {
  2840. return(NULL);
  2841.     }
  2842.     inputStream = xmlNewInputStream(ctxt);
  2843.     if (inputStream == NULL) {
  2844. xmlFreeParserCtxt(ctxt);
  2845. return(NULL);
  2846.     }
  2847.     inputStream->filename = xmlMemStrdup(filename);
  2848.     inputStream->buf = buf;
  2849.     inputStream->base = inputStream->buf->buffer->content;
  2850.     inputStream->cur = inputStream->buf->buffer->content;
  2851.     inputPush(ctxt, inputStream);
  2852.     if ((ctxt->directory == NULL) && (directory == NULL))
  2853.         directory = xmlParserGetDirectory(filename);
  2854.     if ((ctxt->directory == NULL) && (directory != NULL))
  2855.         ctxt->directory = directory;
  2856.     return(ctxt);
  2857. }
  2858. /**
  2859.  * xmlSAXParseFile:
  2860.  * @sax:  the SAX handler block
  2861.  * @filename:  the filename
  2862.  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
  2863.  *             documents
  2864.  *
  2865.  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  2866.  * compressed document is provided by default if found at compile-time.
  2867.  * It use the given SAX function block to handle the parsing callback.
  2868.  * If sax is NULL, fallback to the default DOM tree building routines.
  2869.  *
  2870.  * Returns the resulting document tree
  2871.  */
  2872. xmlDocPtr
  2873. xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
  2874.                           int recovery) {
  2875.     xmlDocPtr ret;
  2876.     xmlParserCtxtPtr ctxt;
  2877.     char *directory = NULL;
  2878.     ctxt = xmlCreateFileParserCtxt(filename);
  2879.     if (ctxt == NULL) return(NULL);
  2880.     if (sax != NULL) {
  2881. if (ctxt->sax != NULL)
  2882.     xmlFree(ctxt->sax);
  2883.         ctxt->sax = sax;
  2884.         ctxt->userData = NULL;
  2885.     }
  2886.     if ((ctxt->directory == NULL) && (directory == NULL))
  2887.         directory = xmlParserGetDirectory(filename);
  2888.     if ((ctxt->directory == NULL) && (directory != NULL))
  2889.         ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
  2890.     xmlParseDocument(ctxt);
  2891.     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
  2892.     else {
  2893.        ret = NULL;
  2894.        xmlFreeDoc(ctxt->myDoc);
  2895.        ctxt->myDoc = NULL;
  2896.     }
  2897.     if (sax != NULL)
  2898.         ctxt->sax = NULL;
  2899.     xmlFreeParserCtxt(ctxt);
  2900.     
  2901.     return(ret);
  2902. }
  2903. /**
  2904.  * xmlParseFile:
  2905.  * @filename:  the filename
  2906.  *
  2907.  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  2908.  * compressed document is provided by default if found at compile-time.
  2909.  *
  2910.  * Returns the resulting document tree
  2911.  */
  2912. xmlDocPtr
  2913. xmlParseFile(const char *filename) {
  2914.     return(xmlSAXParseFile(NULL, filename, 0));
  2915. }
  2916. /**
  2917.  * xmlRecoverFile:
  2918.  * @filename:  the filename
  2919.  *
  2920.  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
  2921.  * compressed document is provided by default if found at compile-time.
  2922.  * In the case the document is not Well Formed, a tree is built anyway
  2923.  *
  2924.  * Returns the resulting document tree
  2925.  */
  2926. xmlDocPtr
  2927. xmlRecoverFile(const char *filename) {
  2928.     return(xmlSAXParseFile(NULL, filename, 1));
  2929. }
  2930. /**
  2931.  * xmlCreateMemoryParserCtxt:
  2932.  * @buffer:  a pointer to a zero terminated char array
  2933.  * @size:  the size of the array (without the trailing 0)
  2934.  *
  2935.  * Create a parser context for an XML in-memory document.
  2936.  *
  2937.  * Returns the new parser context or NULL
  2938.  */
  2939. xmlParserCtxtPtr
  2940. xmlCreateMemoryParserCtxt(char *buffer, int size) {
  2941.     xmlParserCtxtPtr ctxt;
  2942.     xmlParserInputPtr input;
  2943.     if (buffer[size] != 0)
  2944. return(NULL);
  2945.     ctxt = xmlNewParserCtxt();
  2946.     if (ctxt == NULL)
  2947. return(NULL);
  2948.     input = xmlNewInputStream(ctxt);
  2949.     if (input == NULL) {
  2950. xmlFreeParserCtxt(ctxt);
  2951. return(NULL);
  2952.     }
  2953.     input->filename = NULL;
  2954.     input->line = 1;
  2955.     input->col = 1;
  2956.     input->buf = NULL;
  2957.     input->consumed = 0;
  2958.     input->base = BAD_CAST buffer;
  2959.     input->cur = BAD_CAST buffer;
  2960.     input->free = NULL;
  2961.     inputPush(ctxt, input);
  2962.     return(ctxt);
  2963. }
  2964. /**
  2965.  * xmlSAXParseMemory:
  2966.  * @sax:  the SAX handler block
  2967.  * @buffer:  an pointer to a char array
  2968.  * @size:  the size of the array
  2969.  * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
  2970.  *             documents
  2971.  *
  2972.  * parse an XML in-memory block and use the given SAX function block
  2973.  * to handle the parsing callback. If sax is NULL, fallback to the default
  2974.  * DOM tree building routines.
  2975.  * 
  2976.  * Returns the resulting document tree
  2977.  */
  2978. xmlDocPtr
  2979. xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
  2980.     xmlDocPtr ret;
  2981.     xmlParserCtxtPtr ctxt;
  2982.     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
  2983.     if (ctxt == NULL) return(NULL);
  2984.     if (sax != NULL) {
  2985.         ctxt->sax = sax;
  2986.         ctxt->userData = NULL;
  2987.     }
  2988.     xmlParseDocument(ctxt);
  2989.     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
  2990.     else {
  2991.        ret = NULL;
  2992.        xmlFreeDoc(ctxt->myDoc);
  2993.        ctxt->myDoc = NULL;
  2994.     }
  2995.     if (sax != NULL) 
  2996. ctxt->sax = NULL;
  2997.     xmlFreeParserCtxt(ctxt);
  2998.     
  2999.     return(ret);
  3000. }
  3001. /**
  3002.  * xmlParseMemory:
  3003.  * @buffer:  an pointer to a char array
  3004.  * @size:  the size of the array
  3005.  *
  3006.  * parse an XML in-memory block and build a tree.
  3007.  * 
  3008.  * Returns the resulting document tree
  3009.  */
  3010. xmlDocPtr xmlParseMemory(char *buffer, int size) {
  3011.    return(xmlSAXParseMemory(NULL, buffer, size, 0));
  3012. }
  3013. /**
  3014.  * xmlRecoverMemory:
  3015.  * @buffer:  an pointer to a char array
  3016.  * @size:  the size of the array
  3017.  *
  3018.  * parse an XML in-memory block and build a tree.
  3019.  * In the case the document is not Well Formed, a tree is built anyway
  3020.  * 
  3021.  * Returns the resulting document tree
  3022.  */
  3023. xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
  3024.    return(xmlSAXParseMemory(NULL, buffer, size, 1));
  3025. }
  3026. /**
  3027.  * xmlSetupParserForBuffer:
  3028.  * @ctxt:  an XML parser context
  3029.  * @buffer:  a xmlChar * buffer
  3030.  * @filename:  a file name
  3031.  *
  3032.  * Setup the parser context to parse a new buffer; Clears any prior
  3033.  * contents from the parser context. The buffer parameter must not be
  3034.  * NULL, but the filename parameter can be
  3035.  */
  3036. void
  3037. xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
  3038.                              const char* filename)
  3039. {
  3040.     xmlParserInputPtr input;
  3041.     input = xmlNewInputStream(ctxt);
  3042.     if (input == NULL) {
  3043.         perror("malloc");
  3044.         xmlFree(ctxt);
  3045.         return;
  3046.     }
  3047.   
  3048.     xmlClearParserCtxt(ctxt);
  3049.     if (filename != NULL)
  3050.         input->filename = xmlMemStrdup(filename);
  3051.     input->base = buffer;
  3052.     input->cur = buffer;
  3053.     inputPush(ctxt, input);
  3054. }
  3055. /**
  3056.  * xmlSAXUserParseFile:
  3057.  * @sax:  a SAX handler
  3058.  * @user_data:  The user data returned on SAX callbacks
  3059.  * @filename:  a file name
  3060.  *
  3061.  * parse an XML file and call the given SAX handler routines.
  3062.  * Automatic support for ZLIB/Compress compressed document is provided
  3063.  * 
  3064.  * Returns 0 in case of success or a error number otherwise
  3065.  */
  3066. int
  3067. xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
  3068.                     const char *filename) {
  3069.     int ret = 0;
  3070.     xmlParserCtxtPtr ctxt;
  3071.     
  3072.     ctxt = xmlCreateFileParserCtxt(filename);
  3073.     if (ctxt == NULL) return -1;
  3074.     if (ctxt->sax != &xmlDefaultSAXHandler)
  3075. xmlFree(ctxt->sax);
  3076.     ctxt->sax = sax;
  3077.     if (user_data != NULL)
  3078. ctxt->userData = user_data;
  3079.     
  3080.     xmlParseDocument(ctxt);
  3081.     
  3082.     if (ctxt->wellFormed)
  3083. ret = 0;
  3084.     else {
  3085.         if (ctxt->errNo != 0)
  3086.     ret = ctxt->errNo;
  3087. else
  3088.     ret = -1;
  3089.     }
  3090.     if (sax != NULL)
  3091. ctxt->sax = NULL;
  3092.     xmlFreeParserCtxt(ctxt);
  3093.     
  3094.     return ret;
  3095. }
  3096. /**
  3097.  * xmlSAXUserParseMemory:
  3098.  * @sax:  a SAX handler
  3099.  * @user_data:  The user data returned on SAX callbacks
  3100.  * @buffer:  an in-memory XML document input
  3101.  * @size:  the length of the XML document in bytes
  3102.  *
  3103.  * A better SAX parsing routine.
  3104.  * parse an XML in-memory buffer and call the given SAX handler routines.
  3105.  * 
  3106.  * Returns 0 in case of success or a error number otherwise
  3107.  */
  3108. int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
  3109.   char *buffer, int size) {
  3110.     int ret = 0;
  3111.     xmlParserCtxtPtr ctxt;
  3112.     
  3113.     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
  3114.     if (ctxt == NULL) return -1;
  3115.     ctxt->sax = sax;
  3116.     ctxt->userData = user_data;
  3117.     
  3118.     xmlParseDocument(ctxt);
  3119.     
  3120.     if (ctxt->wellFormed)
  3121. ret = 0;
  3122.     else {
  3123.         if (ctxt->errNo != 0)
  3124.     ret = ctxt->errNo;
  3125. else
  3126.     ret = -1;
  3127.     }
  3128.     if (sax != NULL)
  3129. ctxt->sax = NULL;
  3130.     xmlFreeParserCtxt(ctxt);
  3131.     
  3132.     return ret;
  3133. }
  3134. /************************************************************************
  3135.  * *
  3136.  *  Miscellaneous *
  3137.  * *
  3138.  ************************************************************************/
  3139. /**
  3140.  * xmlCleanupParser:
  3141.  *
  3142.  * Cleanup function for the XML parser. It tries to reclaim all
  3143.  * parsing related global memory allocated for the parser processing.
  3144.  * It doesn't deallocate any document related memory. Calling this
  3145.  * function should not prevent reusing the parser.
  3146.  */
  3147. void
  3148. xmlCleanupParser(void) {
  3149.     xmlCleanupCharEncodingHandlers();
  3150.     xmlCleanupPredefinedEntities();
  3151. }
  3152. /**
  3153.  * xmlParserFindNodeInfo:
  3154.  * @ctxt:  an XML parser context
  3155.  * @node:  an XML node within the tree
  3156.  *
  3157.  * Find the parser node info struct for a given node
  3158.  * 
  3159.  * Returns an xmlParserNodeInfo block pointer or NULL
  3160.  */
  3161. const xmlParserNodeInfo* xmlParserFindNodeInfo(const xmlParserCtxt* ctx,
  3162.                                                const xmlNode* node)
  3163. {
  3164.   unsigned long pos;
  3165.   /* Find position where node should be at */
  3166.   pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
  3167.   if ( ctx->node_seq.buffer[pos].node == node )
  3168.     return &ctx->node_seq.buffer[pos];
  3169.   else
  3170.     return NULL;
  3171. }
  3172. /**
  3173.  * xmlInitNodeInfoSeq:
  3174.  * @seq:  a node info sequence pointer
  3175.  *
  3176.  * -- Initialize (set to initial state) node info sequence
  3177.  */
  3178. void
  3179. xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
  3180. {
  3181.   seq->length = 0;
  3182.   seq->maximum = 0;
  3183.   seq->buffer = NULL;
  3184. }
  3185. /**
  3186.  * xmlClearNodeInfoSeq:
  3187.  * @seq:  a node info sequence pointer
  3188.  *
  3189.  * -- Clear (release memory and reinitialize) node
  3190.  *   info sequence
  3191.  */
  3192. void
  3193. xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
  3194. {
  3195.   if ( seq->buffer != NULL )
  3196.     xmlFree(seq->buffer);
  3197.   xmlInitNodeInfoSeq(seq);
  3198. }
  3199. /**
  3200.  * xmlParserFindNodeInfoIndex:
  3201.  * @seq:  a node info sequence pointer
  3202.  * @node:  an XML node pointer
  3203.  *
  3204.  * 
  3205.  * xmlParserFindNodeInfoIndex : Find the index that the info record for
  3206.  *   the given node is or should be at in a sorted sequence
  3207.  *
  3208.  * Returns a long indicating the position of the record
  3209.  */
  3210. unsigned long xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeq* seq,
  3211.                                          const xmlNode* node)
  3212. {
  3213.   unsigned long upper, lower, middle;
  3214.   int found = 0;
  3215.   /* Do a binary search for the key */
  3216.   lower = 1;
  3217.   upper = seq->length;
  3218.   middle = 0;
  3219.   while ( lower <= upper && !found) {
  3220.     middle = lower + (upper - lower) / 2;
  3221.     if ( node == seq->buffer[middle - 1].node )
  3222.       found = 1;
  3223.     else if ( node < seq->buffer[middle - 1].node )
  3224.       upper = middle - 1;
  3225.     else
  3226.       lower = middle + 1;
  3227.   }
  3228.   /* Return position */
  3229.   if ( middle == 0 || seq->buffer[middle - 1].node < node )
  3230.     return middle;
  3231.   else 
  3232.     return middle - 1;
  3233. }
  3234. /**
  3235.  * xmlParserAddNodeInfo:
  3236.  * @ctxt:  an XML parser context
  3237.  * @info:  a node info sequence pointer
  3238.  *
  3239.  * Insert node info record into the sorted sequence
  3240.  */
  3241. void
  3242. xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt, 
  3243.                      const xmlParserNodeInfo* info)
  3244. {
  3245.   unsigned long pos;
  3246.   static unsigned int block_size = 5;
  3247.   /* Find pos and check to see if node is already in the sequence */
  3248.   pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, info->node);
  3249.   if ( pos < ctxt->node_seq.length
  3250.        && ctxt->node_seq.buffer[pos].node == info->node ) {
  3251.     ctxt->node_seq.buffer[pos] = *info;
  3252.   }
  3253.   /* Otherwise, we need to add new node to buffer */
  3254.   else {
  3255.     /* Expand buffer by 5 if needed */
  3256.     if ( ctxt->node_seq.length + 1 > ctxt->node_seq.maximum ) {
  3257.       xmlParserNodeInfo* tmp_buffer;
  3258.       unsigned int byte_size = (sizeof(*ctxt->node_seq.buffer)
  3259.                                 *(ctxt->node_seq.maximum + block_size));
  3260.       if ( ctxt->node_seq.buffer == NULL )
  3261.         tmp_buffer = (xmlParserNodeInfo*) xmlMalloc(byte_size);
  3262.       else 
  3263.         tmp_buffer = (xmlParserNodeInfo*) xmlRealloc(ctxt->node_seq.buffer, byte_size);
  3264.       if ( tmp_buffer == NULL ) {
  3265.         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  3266.     ctxt->sax->error(ctxt->userData, "Out of memoryn");
  3267. ctxt->errNo = XML_ERR_NO_MEMORY;
  3268.         return;
  3269.       }
  3270.       ctxt->node_seq.buffer = tmp_buffer;
  3271.       ctxt->node_seq.maximum += block_size;
  3272.     }
  3273.     /* If position is not at end, move elements out of the way */
  3274.     if ( pos != ctxt->node_seq.length ) {
  3275.       unsigned long i;
  3276.       for ( i = ctxt->node_seq.length; i > pos; i-- )
  3277.         ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
  3278.     }
  3279.   
  3280.     /* Copy element and increase length */
  3281.     ctxt->node_seq.buffer[pos] = *info;
  3282.     ctxt->node_seq.length++;
  3283.   }   
  3284. }
  3285. /**
  3286.  * xmlSubstituteEntitiesDefault:
  3287.  * @val:  int 0 or 1 
  3288.  *
  3289.  * Set and return the previous value for default entity support.
  3290.  * Initially the parser always keep entity references instead of substituting
  3291.  * entity values in the output. This function has to be used to change the
  3292.  * default parser behaviour
  3293.  * SAX::subtituteEntities() has to be used for changing that on a file by
  3294.  * file basis.
  3295.  *
  3296.  * Returns the last value for 0 for no substitution, 1 for substitution.
  3297.  */
  3298. int
  3299. xmlSubstituteEntitiesDefault(int val) {
  3300.     int old = xmlSubstituteEntitiesDefaultValue;
  3301.     xmlSubstituteEntitiesDefaultValue = val;
  3302.     return(old);
  3303. }
  3304. /**
  3305.  * xmlKeepBlanksDefault:
  3306.  * @val:  int 0 or 1 
  3307.  *
  3308.  * Set and return the previous value for default blanks text nodes support.
  3309.  * The 1.x version of the parser used an heuristic to try to detect
  3310.  * ignorable white spaces. As a result the SAX callback was generating
  3311.  * ignorableWhitespace() callbacks instead of characters() one, and when
  3312.  * using the DOM output text nodes containing those blanks were not generated.
  3313.  * The 2.x and later version will switch to the XML standard way and
  3314.  * ignorableWhitespace() are only generated when running the parser in
  3315.  * validating mode and when the current element doesn't allow CDATA or
  3316.  * mixed content.
  3317.  * This function is provided as a way to force the standard behaviour 
  3318.  * on 1.X libs and to switch back to the old mode for compatibility when
  3319.  * running 1.X client code on 2.X . Upgrade of 1.X code should be done
  3320.  * by using xmlIsBlankNode() commodity function to detect the "empty"
  3321.  * nodes generated.
  3322.  * This value also affect autogeneration of indentation when saving code
  3323.  * if blanks sections are kept, indentation is not generated.
  3324.  *
  3325.  * Returns the last value for 0 for no substitution, 1 for substitution.
  3326.  */
  3327. int
  3328. xmlKeepBlanksDefault(int val) {
  3329.     int old = xmlKeepBlanksDefaultValue;
  3330.     xmlKeepBlanksDefaultValue = val;
  3331.     xmlIndentTreeOutput = !val;
  3332.     return(old);
  3333. }