Annotation of embedaddon/libxml2/HTMLparser.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * HTMLparser.c : an HTML 4.0 non-verifying parser
        !             3:  *
        !             4:  * See Copyright for the status of this software.
        !             5:  *
        !             6:  * daniel@veillard.com
        !             7:  */
        !             8: 
        !             9: #define IN_LIBXML
        !            10: #include "libxml.h"
        !            11: #ifdef LIBXML_HTML_ENABLED
        !            12: 
        !            13: #include <string.h>
        !            14: #ifdef HAVE_CTYPE_H
        !            15: #include <ctype.h>
        !            16: #endif
        !            17: #ifdef HAVE_STDLIB_H
        !            18: #include <stdlib.h>
        !            19: #endif
        !            20: #ifdef HAVE_SYS_STAT_H
        !            21: #include <sys/stat.h>
        !            22: #endif
        !            23: #ifdef HAVE_FCNTL_H
        !            24: #include <fcntl.h>
        !            25: #endif
        !            26: #ifdef HAVE_UNISTD_H
        !            27: #include <unistd.h>
        !            28: #endif
        !            29: #ifdef HAVE_ZLIB_H
        !            30: #include <zlib.h>
        !            31: #endif
        !            32: 
        !            33: #include <libxml/xmlmemory.h>
        !            34: #include <libxml/tree.h>
        !            35: #include <libxml/parser.h>
        !            36: #include <libxml/parserInternals.h>
        !            37: #include <libxml/xmlerror.h>
        !            38: #include <libxml/HTMLparser.h>
        !            39: #include <libxml/HTMLtree.h>
        !            40: #include <libxml/entities.h>
        !            41: #include <libxml/encoding.h>
        !            42: #include <libxml/valid.h>
        !            43: #include <libxml/xmlIO.h>
        !            44: #include <libxml/globals.h>
        !            45: #include <libxml/uri.h>
        !            46: 
        !            47: #define HTML_MAX_NAMELEN 1000
        !            48: #define HTML_PARSER_BIG_BUFFER_SIZE 1000
        !            49: #define HTML_PARSER_BUFFER_SIZE 100
        !            50: 
        !            51: /* #define DEBUG */
        !            52: /* #define DEBUG_PUSH */
        !            53: 
        !            54: static int htmlOmittedDefaultValue = 1;
        !            55: 
        !            56: xmlChar * htmlDecodeEntities(htmlParserCtxtPtr ctxt, int len,
        !            57:                             xmlChar end, xmlChar  end2, xmlChar end3);
        !            58: static void htmlParseComment(htmlParserCtxtPtr ctxt);
        !            59: 
        !            60: /************************************************************************
        !            61:  *                                                                     *
        !            62:  *             Some factorized error routines                          *
        !            63:  *                                                                     *
        !            64:  ************************************************************************/
        !            65: 
        !            66: /**
        !            67:  * htmlErrMemory:
        !            68:  * @ctxt:  an HTML parser context
        !            69:  * @extra:  extra informations
        !            70:  *
        !            71:  * Handle a redefinition of attribute error
        !            72:  */
        !            73: static void
        !            74: htmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra)
        !            75: {
        !            76:     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        !            77:         (ctxt->instate == XML_PARSER_EOF))
        !            78:        return;
        !            79:     if (ctxt != NULL) {
        !            80:         ctxt->errNo = XML_ERR_NO_MEMORY;
        !            81:         ctxt->instate = XML_PARSER_EOF;
        !            82:         ctxt->disableSAX = 1;
        !            83:     }
        !            84:     if (extra)
        !            85:         __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
        !            86:                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
        !            87:                         NULL, NULL, 0, 0,
        !            88:                         "Memory allocation failed : %s\n", extra);
        !            89:     else
        !            90:         __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
        !            91:                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
        !            92:                         NULL, NULL, 0, 0, "Memory allocation failed\n");
        !            93: }
        !            94: 
        !            95: /**
        !            96:  * htmlParseErr:
        !            97:  * @ctxt:  an HTML parser context
        !            98:  * @error:  the error number
        !            99:  * @msg:  the error message
        !           100:  * @str1:  string infor
        !           101:  * @str2:  string infor
        !           102:  *
        !           103:  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
        !           104:  */
        !           105: static void
        !           106: htmlParseErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
        !           107:              const char *msg, const xmlChar *str1, const xmlChar *str2)
        !           108: {
        !           109:     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        !           110:         (ctxt->instate == XML_PARSER_EOF))
        !           111:        return;
        !           112:     if (ctxt != NULL)
        !           113:        ctxt->errNo = error;
        !           114:     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error,
        !           115:                     XML_ERR_ERROR, NULL, 0,
        !           116:                    (const char *) str1, (const char *) str2,
        !           117:                    NULL, 0, 0,
        !           118:                    msg, str1, str2);
        !           119:     if (ctxt != NULL)
        !           120:        ctxt->wellFormed = 0;
        !           121: }
        !           122: 
        !           123: /**
        !           124:  * htmlParseErrInt:
        !           125:  * @ctxt:  an HTML parser context
        !           126:  * @error:  the error number
        !           127:  * @msg:  the error message
        !           128:  * @val:  integer info
        !           129:  *
        !           130:  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
        !           131:  */
        !           132: static void
        !           133: htmlParseErrInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
        !           134:              const char *msg, int val)
        !           135: {
        !           136:     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        !           137:         (ctxt->instate == XML_PARSER_EOF))
        !           138:        return;
        !           139:     if (ctxt != NULL)
        !           140:        ctxt->errNo = error;
        !           141:     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error,
        !           142:                     XML_ERR_ERROR, NULL, 0, NULL, NULL,
        !           143:                    NULL, val, 0, msg, val);
        !           144:     if (ctxt != NULL)
        !           145:        ctxt->wellFormed = 0;
        !           146: }
        !           147: 
        !           148: /************************************************************************
        !           149:  *                                                                     *
        !           150:  *     Parser stacks related functions and macros              *
        !           151:  *                                                                     *
        !           152:  ************************************************************************/
        !           153: 
        !           154: /**
        !           155:  * htmlnamePush:
        !           156:  * @ctxt:  an HTML parser context
        !           157:  * @value:  the element name
        !           158:  *
        !           159:  * Pushes a new element name on top of the name stack
        !           160:  *
        !           161:  * Returns 0 in case of error, the index in the stack otherwise
        !           162:  */
        !           163: static int
        !           164: htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value)
        !           165: {
        !           166:     if ((ctxt->html < 3) && (xmlStrEqual(value, BAD_CAST "head")))
        !           167:         ctxt->html = 3;
        !           168:     if ((ctxt->html < 10) && (xmlStrEqual(value, BAD_CAST "body")))
        !           169:         ctxt->html = 10;
        !           170:     if (ctxt->nameNr >= ctxt->nameMax) {
        !           171:         ctxt->nameMax *= 2;
        !           172:         ctxt->nameTab = (const xmlChar * *)
        !           173:                          xmlRealloc((xmlChar * *)ctxt->nameTab,
        !           174:                                     ctxt->nameMax *
        !           175:                                     sizeof(ctxt->nameTab[0]));
        !           176:         if (ctxt->nameTab == NULL) {
        !           177:             htmlErrMemory(ctxt, NULL);
        !           178:             return (0);
        !           179:         }
        !           180:     }
        !           181:     ctxt->nameTab[ctxt->nameNr] = value;
        !           182:     ctxt->name = value;
        !           183:     return (ctxt->nameNr++);
        !           184: }
        !           185: /**
        !           186:  * htmlnamePop:
        !           187:  * @ctxt: an HTML parser context
        !           188:  *
        !           189:  * Pops the top element name from the name stack
        !           190:  *
        !           191:  * Returns the name just removed
        !           192:  */
        !           193: static const xmlChar *
        !           194: htmlnamePop(htmlParserCtxtPtr ctxt)
        !           195: {
        !           196:     const xmlChar *ret;
        !           197: 
        !           198:     if (ctxt->nameNr <= 0)
        !           199:         return (NULL);
        !           200:     ctxt->nameNr--;
        !           201:     if (ctxt->nameNr < 0)
        !           202:         return (NULL);
        !           203:     if (ctxt->nameNr > 0)
        !           204:         ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
        !           205:     else
        !           206:         ctxt->name = NULL;
        !           207:     ret = ctxt->nameTab[ctxt->nameNr];
        !           208:     ctxt->nameTab[ctxt->nameNr] = NULL;
        !           209:     return (ret);
        !           210: }
        !           211: 
        !           212: /**
        !           213:  * htmlNodeInfoPush:
        !           214:  * @ctxt:  an HTML parser context
        !           215:  * @value:  the node info
        !           216:  *
        !           217:  * Pushes a new element name on top of the node info stack
        !           218:  *
        !           219:  * Returns 0 in case of error, the index in the stack otherwise
        !           220:  */
        !           221: static int
        !           222: htmlNodeInfoPush(htmlParserCtxtPtr ctxt, htmlParserNodeInfo *value)
        !           223: {
        !           224:     if (ctxt->nodeInfoNr >= ctxt->nodeInfoMax) {
        !           225:         if (ctxt->nodeInfoMax == 0)
        !           226:                 ctxt->nodeInfoMax = 5;
        !           227:         ctxt->nodeInfoMax *= 2;
        !           228:         ctxt->nodeInfoTab = (htmlParserNodeInfo *)
        !           229:                          xmlRealloc((htmlParserNodeInfo *)ctxt->nodeInfoTab,
        !           230:                                     ctxt->nodeInfoMax *
        !           231:                                     sizeof(ctxt->nodeInfoTab[0]));
        !           232:         if (ctxt->nodeInfoTab == NULL) {
        !           233:             htmlErrMemory(ctxt, NULL);
        !           234:             return (0);
        !           235:         }
        !           236:     }
        !           237:     ctxt->nodeInfoTab[ctxt->nodeInfoNr] = *value;
        !           238:     ctxt->nodeInfo = &ctxt->nodeInfoTab[ctxt->nodeInfoNr];
        !           239:     return (ctxt->nodeInfoNr++);
        !           240: }
        !           241: 
        !           242: /**
        !           243:  * htmlNodeInfoPop:
        !           244:  * @ctxt:  an HTML parser context
        !           245:  *
        !           246:  * Pops the top element name from the node info stack
        !           247:  *
        !           248:  * Returns 0 in case of error, the pointer to NodeInfo otherwise
        !           249:  */
        !           250: static htmlParserNodeInfo *
        !           251: htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
        !           252: {
        !           253:     if (ctxt->nodeInfoNr <= 0)
        !           254:         return (NULL);
        !           255:     ctxt->nodeInfoNr--;
        !           256:     if (ctxt->nodeInfoNr < 0)
        !           257:         return (NULL);
        !           258:     if (ctxt->nodeInfoNr > 0)
        !           259:         ctxt->nodeInfo = &ctxt->nodeInfoTab[ctxt->nodeInfoNr - 1];
        !           260:     else
        !           261:         ctxt->nodeInfo = NULL;
        !           262:     return &ctxt->nodeInfoTab[ctxt->nodeInfoNr];
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * Macros for accessing the content. Those should be used only by the parser,
        !           267:  * and not exported.
        !           268:  *
        !           269:  * Dirty macros, i.e. one need to make assumption on the context to use them
        !           270:  *
        !           271:  *   CUR_PTR return the current pointer to the xmlChar to be parsed.
        !           272:  *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
        !           273:  *           in ISO-Latin or UTF-8, and the current 16 bit value if compiled
        !           274:  *           in UNICODE mode. This should be used internally by the parser
        !           275:  *           only to compare to ASCII values otherwise it would break when
        !           276:  *           running with UTF-8 encoding.
        !           277:  *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
        !           278:  *           to compare on ASCII based substring.
        !           279:  *   UPP(n)  returns the n'th next xmlChar converted to uppercase. Same as CUR
        !           280:  *           it should be used only to compare on ASCII based substring.
        !           281:  *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
        !           282:  *           strings without newlines within the parser.
        !           283:  *
        !           284:  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
        !           285:  *
        !           286:  *   CURRENT Returns the current char value, with the full decoding of
        !           287:  *           UTF-8 if we are using this mode. It returns an int.
        !           288:  *   NEXT    Skip to the next character, this does the proper decoding
        !           289:  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
        !           290:  *   NEXTL(l) Skip the current unicode character of l xmlChars long.
        !           291:  *   COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
        !           292:  */
        !           293: 
        !           294: #define UPPER (toupper(*ctxt->input->cur))
        !           295: 
        !           296: #define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val)
        !           297: 
        !           298: #define NXT(val) ctxt->input->cur[(val)]
        !           299: 
        !           300: #define UPP(val) (toupper(ctxt->input->cur[(val)]))
        !           301: 
        !           302: #define CUR_PTR ctxt->input->cur
        !           303: 
        !           304: #define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
        !           305:                   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
        !           306:        xmlParserInputShrink(ctxt->input)
        !           307: 
        !           308: #define GROW if ((ctxt->progressive == 0) &&                           \
        !           309:                 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
        !           310:        xmlParserInputGrow(ctxt->input, INPUT_CHUNK)
        !           311: 
        !           312: #define CURRENT ((int) (*ctxt->input->cur))
        !           313: 
        !           314: #define SKIP_BLANKS htmlSkipBlankChars(ctxt)
        !           315: 
        !           316: /* Inported from XML */
        !           317: 
        !           318: /* #define CUR (ctxt->token ? ctxt->token : (int) (*ctxt->input->cur)) */
        !           319: #define CUR ((int) (*ctxt->input->cur))
        !           320: #define NEXT xmlNextChar(ctxt)
        !           321: 
        !           322: #define RAW (ctxt->token ? -1 : (*ctxt->input->cur))
        !           323: 
        !           324: 
        !           325: #define NEXTL(l) do {                                                  \
        !           326:     if (*(ctxt->input->cur) == '\n') {                                 \
        !           327:        ctxt->input->line++; ctxt->input->col = 1;                      \
        !           328:     } else ctxt->input->col++;                                         \
        !           329:     ctxt->token = 0; ctxt->input->cur += l; ctxt->nbChars++;           \
        !           330:   } while (0)
        !           331: 
        !           332: /************
        !           333:     \
        !           334:     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);    \
        !           335:     if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt);
        !           336:  ************/
        !           337: 
        !           338: #define CUR_CHAR(l) htmlCurrentChar(ctxt, &l)
        !           339: #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
        !           340: 
        !           341: #define COPY_BUF(l,b,i,v)                                              \
        !           342:     if (l == 1) b[i++] = (xmlChar) v;                                  \
        !           343:     else i += xmlCopyChar(l,&b[i],v)
        !           344: 
        !           345: /**
        !           346:  * htmlFindEncoding:
        !           347:  * @the HTML parser context
        !           348:  *
        !           349:  * Ty to find and encoding in the current data available in the input
        !           350:  * buffer this is needed to try to switch to the proper encoding when
        !           351:  * one face a character error.
        !           352:  * That's an heuristic, since it's operating outside of parsing it could
        !           353:  * try to use a meta which had been commented out, that's the reason it
        !           354:  * should only be used in case of error, not as a default.
        !           355:  *
        !           356:  * Returns an encoding string or NULL if not found, the string need to
        !           357:  *   be freed
        !           358:  */
        !           359: static xmlChar *
        !           360: htmlFindEncoding(xmlParserCtxtPtr ctxt) {
        !           361:     const xmlChar *start, *cur, *end;
        !           362: 
        !           363:     if ((ctxt == NULL) || (ctxt->input == NULL) ||
        !           364:         (ctxt->input->encoding != NULL) || (ctxt->input->buf == NULL) ||
        !           365:         (ctxt->input->buf->encoder != NULL))
        !           366:         return(NULL);
        !           367:     if ((ctxt->input->cur == NULL) || (ctxt->input->end == NULL))
        !           368:         return(NULL);
        !           369: 
        !           370:     start = ctxt->input->cur;
        !           371:     end = ctxt->input->end;
        !           372:     /* we also expect the input buffer to be zero terminated */
        !           373:     if (*end != 0)
        !           374:         return(NULL);
        !           375: 
        !           376:     cur = xmlStrcasestr(start, BAD_CAST "HTTP-EQUIV");
        !           377:     if (cur == NULL)
        !           378:         return(NULL);
        !           379:     cur = xmlStrcasestr(cur, BAD_CAST  "CONTENT");
        !           380:     if (cur == NULL)
        !           381:         return(NULL);
        !           382:     cur = xmlStrcasestr(cur, BAD_CAST  "CHARSET=");
        !           383:     if (cur == NULL)
        !           384:         return(NULL);
        !           385:     cur += 8;
        !           386:     start = cur;
        !           387:     while (((*cur >= 'A') && (*cur <= 'Z')) ||
        !           388:            ((*cur >= 'a') && (*cur <= 'z')) ||
        !           389:            ((*cur >= '0') && (*cur <= '9')) ||
        !           390:            (*cur == '-') || (*cur == '_') || (*cur == ':') || (*cur == '/'))
        !           391:            cur++;
        !           392:     if (cur == start)
        !           393:         return(NULL);
        !           394:     return(xmlStrndup(start, cur - start));
        !           395: }
        !           396: 
        !           397: /**
        !           398:  * htmlCurrentChar:
        !           399:  * @ctxt:  the HTML parser context
        !           400:  * @len:  pointer to the length of the char read
        !           401:  *
        !           402:  * The current char value, if using UTF-8 this may actually span multiple
        !           403:  * bytes in the input buffer. Implement the end of line normalization:
        !           404:  * 2.11 End-of-Line Handling
        !           405:  * If the encoding is unspecified, in the case we find an ISO-Latin-1
        !           406:  * char, then the encoding converter is plugged in automatically.
        !           407:  *
        !           408:  * Returns the current char value and its length
        !           409:  */
        !           410: 
        !           411: static int
        !           412: htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
        !           413:     if (ctxt->instate == XML_PARSER_EOF)
        !           414:        return(0);
        !           415: 
        !           416:     if (ctxt->token != 0) {
        !           417:        *len = 0;
        !           418:        return(ctxt->token);
        !           419:     }
        !           420:     if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
        !           421:        /*
        !           422:         * We are supposed to handle UTF8, check it's valid
        !           423:         * From rfc2044: encoding of the Unicode values on UTF-8:
        !           424:         *
        !           425:         * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
        !           426:         * 0000 0000-0000 007F   0xxxxxxx
        !           427:         * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
        !           428:         * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
        !           429:         *
        !           430:         * Check for the 0x110000 limit too
        !           431:         */
        !           432:        const unsigned char *cur = ctxt->input->cur;
        !           433:        unsigned char c;
        !           434:        unsigned int val;
        !           435: 
        !           436:        c = *cur;
        !           437:        if (c & 0x80) {
        !           438:            if (cur[1] == 0) {
        !           439:                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
        !           440:                 cur = ctxt->input->cur;
        !           441:             }
        !           442:            if ((cur[1] & 0xc0) != 0x80)
        !           443:                goto encoding_error;
        !           444:            if ((c & 0xe0) == 0xe0) {
        !           445: 
        !           446:                if (cur[2] == 0) {
        !           447:                    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
        !           448:                     cur = ctxt->input->cur;
        !           449:                 }
        !           450:                if ((cur[2] & 0xc0) != 0x80)
        !           451:                    goto encoding_error;
        !           452:                if ((c & 0xf0) == 0xf0) {
        !           453:                    if (cur[3] == 0) {
        !           454:                        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
        !           455:                         cur = ctxt->input->cur;
        !           456:                     }
        !           457:                    if (((c & 0xf8) != 0xf0) ||
        !           458:                        ((cur[3] & 0xc0) != 0x80))
        !           459:                        goto encoding_error;
        !           460:                    /* 4-byte code */
        !           461:                    *len = 4;
        !           462:                    val = (cur[0] & 0x7) << 18;
        !           463:                    val |= (cur[1] & 0x3f) << 12;
        !           464:                    val |= (cur[2] & 0x3f) << 6;
        !           465:                    val |= cur[3] & 0x3f;
        !           466:                } else {
        !           467:                  /* 3-byte code */
        !           468:                    *len = 3;
        !           469:                    val = (cur[0] & 0xf) << 12;
        !           470:                    val |= (cur[1] & 0x3f) << 6;
        !           471:                    val |= cur[2] & 0x3f;
        !           472:                }
        !           473:            } else {
        !           474:              /* 2-byte code */
        !           475:                *len = 2;
        !           476:                val = (cur[0] & 0x1f) << 6;
        !           477:                val |= cur[1] & 0x3f;
        !           478:            }
        !           479:            if (!IS_CHAR(val)) {
        !           480:                htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
        !           481:                                "Char 0x%X out of allowed range\n", val);
        !           482:            }
        !           483:            return(val);
        !           484:        } else {
        !           485:             if ((*ctxt->input->cur == 0) &&
        !           486:                 (ctxt->input->cur < ctxt->input->end)) {
        !           487:                     htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
        !           488:                                "Char 0x%X out of allowed range\n", 0);
        !           489:                 *len = 1;
        !           490:                 return(' ');
        !           491:             }
        !           492:            /* 1-byte code */
        !           493:            *len = 1;
        !           494:            return((int) *ctxt->input->cur);
        !           495:        }
        !           496:     }
        !           497:     /*
        !           498:      * Assume it's a fixed length encoding (1) with
        !           499:      * a compatible encoding for the ASCII set, since
        !           500:      * XML constructs only use < 128 chars
        !           501:      */
        !           502:     *len = 1;
        !           503:     if ((int) *ctxt->input->cur < 0x80)
        !           504:        return((int) *ctxt->input->cur);
        !           505: 
        !           506:     /*
        !           507:      * Humm this is bad, do an automatic flow conversion
        !           508:      */
        !           509:     {
        !           510:         xmlChar * guess;
        !           511:         xmlCharEncodingHandlerPtr handler;
        !           512: 
        !           513:         guess = htmlFindEncoding(ctxt);
        !           514:         if (guess == NULL) {
        !           515:             xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
        !           516:         } else {
        !           517:             if (ctxt->input->encoding != NULL)
        !           518:                 xmlFree((xmlChar *) ctxt->input->encoding);
        !           519:             ctxt->input->encoding = guess;
        !           520:             handler = xmlFindCharEncodingHandler((const char *) guess);
        !           521:             if (handler != NULL) {
        !           522:                 xmlSwitchToEncoding(ctxt, handler);
        !           523:             } else {
        !           524:                 htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
        !           525:                              "Unsupported encoding %s", guess, NULL);
        !           526:             }
        !           527:         }
        !           528:         ctxt->charset = XML_CHAR_ENCODING_UTF8;
        !           529:     }
        !           530: 
        !           531:     return(xmlCurrentChar(ctxt, len));
        !           532: 
        !           533: encoding_error:
        !           534:     /*
        !           535:      * If we detect an UTF8 error that probably mean that the
        !           536:      * input encoding didn't get properly advertized in the
        !           537:      * declaration header. Report the error and switch the encoding
        !           538:      * to ISO-Latin-1 (if you don't like this policy, just declare the
        !           539:      * encoding !)
        !           540:      */
        !           541:     {
        !           542:         char buffer[150];
        !           543: 
        !           544:        if (ctxt->input->end - ctxt->input->cur >= 4) {
        !           545:            snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
        !           546:                            ctxt->input->cur[0], ctxt->input->cur[1],
        !           547:                            ctxt->input->cur[2], ctxt->input->cur[3]);
        !           548:        } else {
        !           549:            snprintf(buffer, 149, "Bytes: 0x%02X\n", ctxt->input->cur[0]);
        !           550:        }
        !           551:        htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
        !           552:                     "Input is not proper UTF-8, indicate encoding !\n",
        !           553:                     BAD_CAST buffer, NULL);
        !           554:     }
        !           555: 
        !           556:     ctxt->charset = XML_CHAR_ENCODING_8859_1;
        !           557:     *len = 1;
        !           558:     return((int) *ctxt->input->cur);
        !           559: }
        !           560: 
        !           561: /**
        !           562:  * htmlSkipBlankChars:
        !           563:  * @ctxt:  the HTML parser context
        !           564:  *
        !           565:  * skip all blanks character found at that point in the input streams.
        !           566:  *
        !           567:  * Returns the number of space chars skipped
        !           568:  */
        !           569: 
        !           570: static int
        !           571: htmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
        !           572:     int res = 0;
        !           573: 
        !           574:     while (IS_BLANK_CH(*(ctxt->input->cur))) {
        !           575:        if ((*ctxt->input->cur == 0) &&
        !           576:            (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {
        !           577:                xmlPopInput(ctxt);
        !           578:        } else {
        !           579:            if (*(ctxt->input->cur) == '\n') {
        !           580:                ctxt->input->line++; ctxt->input->col = 1;
        !           581:            } else ctxt->input->col++;
        !           582:            ctxt->input->cur++;
        !           583:            ctxt->nbChars++;
        !           584:            if (*ctxt->input->cur == 0)
        !           585:                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
        !           586:        }
        !           587:        res++;
        !           588:     }
        !           589:     return(res);
        !           590: }
        !           591: 
        !           592: 
        !           593: 
        !           594: /************************************************************************
        !           595:  *                                                                     *
        !           596:  *     The list of HTML elements and their properties          *
        !           597:  *                                                                     *
        !           598:  ************************************************************************/
        !           599: 
        !           600: /*
        !           601:  *  Start Tag: 1 means the start tag can be ommited
        !           602:  *  End Tag:   1 means the end tag can be ommited
        !           603:  *             2 means it's forbidden (empty elements)
        !           604:  *             3 means the tag is stylistic and should be closed easily
        !           605:  *  Depr:      this element is deprecated
        !           606:  *  DTD:       1 means that this element is valid only in the Loose DTD
        !           607:  *             2 means that this element is valid only in the Frameset DTD
        !           608:  *
        !           609:  * Name,Start Tag,End Tag,Save End,Empty,Deprecated,DTD,inline,Description
        !           610:        , subElements , impliedsubelt , Attributes, userdata
        !           611:  */
        !           612: 
        !           613: /* Definitions and a couple of vars for HTML Elements */
        !           614: 
        !           615: #define FONTSTYLE "tt", "i", "b", "u", "s", "strike", "big", "small"
        !           616: #define NB_FONTSTYLE 8
        !           617: #define PHRASE "em", "strong", "dfn", "code", "samp", "kbd", "var", "cite", "abbr", "acronym"
        !           618: #define NB_PHRASE 10
        !           619: #define SPECIAL "a", "img", "applet", "embed", "object", "font", "basefont", "br", "script", "map", "q", "sub", "sup", "span", "bdo", "iframe"
        !           620: #define NB_SPECIAL 16
        !           621: #define INLINE FONTSTYLE, PHRASE, SPECIAL, FORMCTRL
        !           622: #define NB_INLINE NB_PCDATA + NB_FONTSTYLE + NB_PHRASE + NB_SPECIAL + NB_FORMCTRL
        !           623: #define BLOCK HEADING, LIST, "pre", "p", "dl", "div", "center", "noscript", "noframes", "blockquote", "form", "isindex", "hr", "table", "fieldset", "address"
        !           624: #define NB_BLOCK NB_HEADING + NB_LIST + 14
        !           625: #define FORMCTRL "input", "select", "textarea", "label", "button"
        !           626: #define NB_FORMCTRL 5
        !           627: #define PCDATA
        !           628: #define NB_PCDATA 0
        !           629: #define HEADING "h1", "h2", "h3", "h4", "h5", "h6"
        !           630: #define NB_HEADING 6
        !           631: #define LIST "ul", "ol", "dir", "menu"
        !           632: #define NB_LIST 4
        !           633: #define MODIFIER
        !           634: #define NB_MODIFIER 0
        !           635: #define FLOW BLOCK,INLINE
        !           636: #define NB_FLOW NB_BLOCK + NB_INLINE
        !           637: #define EMPTY NULL
        !           638: 
        !           639: 
        !           640: static const char* const html_flow[] = { FLOW, NULL } ;
        !           641: static const char* const html_inline[] = { INLINE, NULL } ;
        !           642: 
        !           643: /* placeholders: elts with content but no subelements */
        !           644: static const char* const html_pcdata[] = { NULL } ;
        !           645: #define html_cdata html_pcdata
        !           646: 
        !           647: 
        !           648: /* ... and for HTML Attributes */
        !           649: 
        !           650: #define COREATTRS "id", "class", "style", "title"
        !           651: #define NB_COREATTRS 4
        !           652: #define I18N "lang", "dir"
        !           653: #define NB_I18N 2
        !           654: #define EVENTS "onclick", "ondblclick", "onmousedown", "onmouseup", "onmouseover", "onmouseout", "onkeypress", "onkeydown", "onkeyup"
        !           655: #define NB_EVENTS 9
        !           656: #define ATTRS COREATTRS,I18N,EVENTS
        !           657: #define NB_ATTRS NB_NB_COREATTRS + NB_I18N + NB_EVENTS
        !           658: #define CELLHALIGN "align", "char", "charoff"
        !           659: #define NB_CELLHALIGN 3
        !           660: #define CELLVALIGN "valign"
        !           661: #define NB_CELLVALIGN 1
        !           662: 
        !           663: static const char* const html_attrs[] = { ATTRS, NULL } ;
        !           664: static const char* const core_i18n_attrs[] = { COREATTRS, I18N, NULL } ;
        !           665: static const char* const core_attrs[] = { COREATTRS, NULL } ;
        !           666: static const char* const i18n_attrs[] = { I18N, NULL } ;
        !           667: 
        !           668: 
        !           669: /* Other declarations that should go inline ... */
        !           670: static const char* const a_attrs[] = { ATTRS, "charset", "type", "name",
        !           671:        "href", "hreflang", "rel", "rev", "accesskey", "shape", "coords",
        !           672:        "tabindex", "onfocus", "onblur", NULL } ;
        !           673: static const char* const target_attr[] = { "target", NULL } ;
        !           674: static const char* const rows_cols_attr[] = { "rows", "cols", NULL } ;
        !           675: static const char* const alt_attr[] = { "alt", NULL } ;
        !           676: static const char* const src_alt_attrs[] = { "src", "alt", NULL } ;
        !           677: static const char* const href_attrs[] = { "href", NULL } ;
        !           678: static const char* const clear_attrs[] = { "clear", NULL } ;
        !           679: static const char* const inline_p[] = { INLINE, "p", NULL } ;
        !           680: 
        !           681: static const char* const flow_param[] = { FLOW, "param", NULL } ;
        !           682: static const char* const applet_attrs[] = { COREATTRS , "codebase",
        !           683:                "archive", "alt", "name", "height", "width", "align",
        !           684:                "hspace", "vspace", NULL } ;
        !           685: static const char* const area_attrs[] = { "shape", "coords", "href", "nohref",
        !           686:        "tabindex", "accesskey", "onfocus", "onblur", NULL } ;
        !           687: static const char* const basefont_attrs[] =
        !           688:        { "id", "size", "color", "face", NULL } ;
        !           689: static const char* const quote_attrs[] = { ATTRS, "cite", NULL } ;
        !           690: static const char* const body_contents[] = { FLOW, "ins", "del", NULL } ;
        !           691: static const char* const body_attrs[] = { ATTRS, "onload", "onunload", NULL } ;
        !           692: static const char* const body_depr[] = { "background", "bgcolor", "text",
        !           693:        "link", "vlink", "alink", NULL } ;
        !           694: static const char* const button_attrs[] = { ATTRS, "name", "value", "type",
        !           695:        "disabled", "tabindex", "accesskey", "onfocus", "onblur", NULL } ;
        !           696: 
        !           697: 
        !           698: static const char* const col_attrs[] = { ATTRS, "span", "width", CELLHALIGN, CELLVALIGN, NULL } ;
        !           699: static const char* const col_elt[] = { "col", NULL } ;
        !           700: static const char* const edit_attrs[] = { ATTRS, "datetime", "cite", NULL } ;
        !           701: static const char* const compact_attrs[] = { ATTRS, "compact", NULL } ;
        !           702: static const char* const dl_contents[] = { "dt", "dd", NULL } ;
        !           703: static const char* const compact_attr[] = { "compact", NULL } ;
        !           704: static const char* const label_attr[] = { "label", NULL } ;
        !           705: static const char* const fieldset_contents[] = { FLOW, "legend" } ;
        !           706: static const char* const font_attrs[] = { COREATTRS, I18N, "size", "color", "face" , NULL } ;
        !           707: static const char* const form_contents[] = { HEADING, LIST, INLINE, "pre", "p", "div", "center", "noscript", "noframes", "blockquote", "isindex", "hr", "table", "fieldset", "address", NULL } ;
        !           708: static const char* const form_attrs[] = { ATTRS, "method", "enctype", "accept", "name", "onsubmit", "onreset", "accept-charset", NULL } ;
        !           709: static const char* const frame_attrs[] = { COREATTRS, "longdesc", "name", "src", "frameborder", "marginwidth", "marginheight", "noresize", "scrolling" , NULL } ;
        !           710: static const char* const frameset_attrs[] = { COREATTRS, "rows", "cols", "onload", "onunload", NULL } ;
        !           711: static const char* const frameset_contents[] = { "frameset", "frame", "noframes", NULL } ;
        !           712: static const char* const head_attrs[] = { I18N, "profile", NULL } ;
        !           713: static const char* const head_contents[] = { "title", "isindex", "base", "script", "style", "meta", "link", "object", NULL } ;
        !           714: static const char* const hr_depr[] = { "align", "noshade", "size", "width", NULL } ;
        !           715: static const char* const version_attr[] = { "version", NULL } ;
        !           716: static const char* const html_content[] = { "head", "body", "frameset", NULL } ;
        !           717: static const char* const iframe_attrs[] = { COREATTRS, "longdesc", "name", "src", "frameborder", "marginwidth", "marginheight", "scrolling", "align", "height", "width", NULL } ;
        !           718: static const char* const img_attrs[] = { ATTRS, "longdesc", "name", "height", "width", "usemap", "ismap", NULL } ;
        !           719: static const char* const embed_attrs[] = { COREATTRS, "align", "alt", "border", "code", "codebase", "frameborder", "height", "hidden", "hspace", "name", "palette", "pluginspace", "pluginurl", "src", "type", "units", "vspace", "width", NULL } ;
        !           720: static const char* const input_attrs[] = { ATTRS, "type", "name", "value", "checked", "disabled", "readonly", "size", "maxlength", "src", "alt", "usemap", "ismap", "tabindex", "accesskey", "onfocus", "onblur", "onselect", "onchange", "accept", NULL } ;
        !           721: static const char* const prompt_attrs[] = { COREATTRS, I18N, "prompt", NULL } ;
        !           722: static const char* const label_attrs[] = { ATTRS, "for", "accesskey", "onfocus", "onblur", NULL } ;
        !           723: static const char* const legend_attrs[] = { ATTRS, "accesskey", NULL } ;
        !           724: static const char* const align_attr[] = { "align", NULL } ;
        !           725: static const char* const link_attrs[] = { ATTRS, "charset", "href", "hreflang", "type", "rel", "rev", "media", NULL } ;
        !           726: static const char* const map_contents[] = { BLOCK, "area", NULL } ;
        !           727: static const char* const name_attr[] = { "name", NULL } ;
        !           728: static const char* const action_attr[] = { "action", NULL } ;
        !           729: static const char* const blockli_elt[] = { BLOCK, "li", NULL } ;
        !           730: static const char* const meta_attrs[] = { I18N, "http-equiv", "name", "scheme", NULL } ;
        !           731: static const char* const content_attr[] = { "content", NULL } ;
        !           732: static const char* const type_attr[] = { "type", NULL } ;
        !           733: static const char* const noframes_content[] = { "body", FLOW MODIFIER, NULL } ;
        !           734: static const char* const object_contents[] = { FLOW, "param", NULL } ;
        !           735: static const char* const object_attrs[] = { ATTRS, "declare", "classid", "codebase", "data", "type", "codetype", "archive", "standby", "height", "width", "usemap", "name", "tabindex", NULL } ;
        !           736: static const char* const object_depr[] = { "align", "border", "hspace", "vspace", NULL } ;
        !           737: static const char* const ol_attrs[] = { "type", "compact", "start", NULL} ;
        !           738: static const char* const option_elt[] = { "option", NULL } ;
        !           739: static const char* const optgroup_attrs[] = { ATTRS, "disabled", NULL } ;
        !           740: static const char* const option_attrs[] = { ATTRS, "disabled", "label", "selected", "value", NULL } ;
        !           741: static const char* const param_attrs[] = { "id", "value", "valuetype", "type", NULL } ;
        !           742: static const char* const width_attr[] = { "width", NULL } ;
        !           743: static const char* const pre_content[] = { PHRASE, "tt", "i", "b", "u", "s", "strike", "a", "br", "script", "map", "q", "span", "bdo", "iframe", NULL } ;
        !           744: static const char* const script_attrs[] = { "charset", "src", "defer", "event", "for", NULL } ;
        !           745: static const char* const language_attr[] = { "language", NULL } ;
        !           746: static const char* const select_content[] = { "optgroup", "option", NULL } ;
        !           747: static const char* const select_attrs[] = { ATTRS, "name", "size", "multiple", "disabled", "tabindex", "onfocus", "onblur", "onchange", NULL } ;
        !           748: static const char* const style_attrs[] = { I18N, "media", "title", NULL } ;
        !           749: static const char* const table_attrs[] = { ATTRS, "summary", "width", "border", "frame", "rules", "cellspacing", "cellpadding", "datapagesize", NULL } ;
        !           750: static const char* const table_depr[] = { "align", "bgcolor", NULL } ;
        !           751: static const char* const table_contents[] = { "caption", "col", "colgroup", "thead", "tfoot", "tbody", "tr", NULL} ;
        !           752: static const char* const tr_elt[] = { "tr", NULL } ;
        !           753: static const char* const talign_attrs[] = { ATTRS, CELLHALIGN, CELLVALIGN, NULL} ;
        !           754: static const char* const th_td_depr[] = { "nowrap", "bgcolor", "width", "height", NULL } ;
        !           755: static const char* const th_td_attr[] = { ATTRS, "abbr", "axis", "headers", "scope", "rowspan", "colspan", CELLHALIGN, CELLVALIGN, NULL } ;
        !           756: static const char* const textarea_attrs[] = { ATTRS, "name", "disabled", "readonly", "tabindex", "accesskey", "onfocus", "onblur", "onselect", "onchange", NULL } ;
        !           757: static const char* const tr_contents[] = { "th", "td", NULL } ;
        !           758: static const char* const bgcolor_attr[] = { "bgcolor", NULL } ;
        !           759: static const char* const li_elt[] = { "li", NULL } ;
        !           760: static const char* const ul_depr[] = { "type", "compact", NULL} ;
        !           761: static const char* const dir_attr[] = { "dir", NULL} ;
        !           762: 
        !           763: #define DECL (const char**)
        !           764: 
        !           765: static const htmlElemDesc
        !           766: html40ElementTable[] = {
        !           767: { "a",         0, 0, 0, 0, 0, 0, 1, "anchor ",
        !           768:        DECL html_inline , NULL , DECL a_attrs , DECL target_attr, NULL
        !           769: },
        !           770: { "abbr",      0, 0, 0, 0, 0, 0, 1, "abbreviated form",
        !           771:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           772: },
        !           773: { "acronym",   0, 0, 0, 0, 0, 0, 1, "",
        !           774:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           775: },
        !           776: { "address",   0, 0, 0, 0, 0, 0, 0, "information on author ",
        !           777:        DECL inline_p  , NULL , DECL html_attrs, NULL, NULL
        !           778: },
        !           779: { "applet",    0, 0, 0, 0, 1, 1, 2, "java applet ",
        !           780:        DECL flow_param , NULL , NULL , DECL applet_attrs, NULL
        !           781: },
        !           782: { "area",      0, 2, 2, 1, 0, 0, 0, "client-side image map area ",
        !           783:        EMPTY ,  NULL , DECL area_attrs , DECL target_attr, DECL alt_attr
        !           784: },
        !           785: { "b",         0, 3, 0, 0, 0, 0, 1, "bold text style",
        !           786:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           787: },
        !           788: { "base",      0, 2, 2, 1, 0, 0, 0, "document base uri ",
        !           789:        EMPTY , NULL , NULL , DECL target_attr, DECL href_attrs
        !           790: },
        !           791: { "basefont",  0, 2, 2, 1, 1, 1, 1, "base font size " ,
        !           792:        EMPTY , NULL , NULL, DECL basefont_attrs, NULL
        !           793: },
        !           794: { "bdo",       0, 0, 0, 0, 0, 0, 1, "i18n bidi over-ride ",
        !           795:        DECL html_inline , NULL , DECL core_i18n_attrs, NULL, DECL dir_attr
        !           796: },
        !           797: { "big",       0, 3, 0, 0, 0, 0, 1, "large text style",
        !           798:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           799: },
        !           800: { "blockquote",        0, 0, 0, 0, 0, 0, 0, "long quotation ",
        !           801:        DECL html_flow , NULL , DECL quote_attrs , NULL, NULL
        !           802: },
        !           803: { "body",      1, 1, 0, 0, 0, 0, 0, "document body ",
        !           804:        DECL body_contents , "div" , DECL body_attrs, DECL body_depr, NULL
        !           805: },
        !           806: { "br",                0, 2, 2, 1, 0, 0, 1, "forced line break ",
        !           807:        EMPTY , NULL , DECL core_attrs, DECL clear_attrs , NULL
        !           808: },
        !           809: { "button",    0, 0, 0, 0, 0, 0, 2, "push button ",
        !           810:        DECL html_flow MODIFIER , NULL , DECL button_attrs, NULL, NULL
        !           811: },
        !           812: { "caption",   0, 0, 0, 0, 0, 0, 0, "table caption ",
        !           813:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           814: },
        !           815: { "center",    0, 3, 0, 0, 1, 1, 0, "shorthand for div align=center ",
        !           816:        DECL html_flow , NULL , NULL, DECL html_attrs, NULL
        !           817: },
        !           818: { "cite",      0, 0, 0, 0, 0, 0, 1, "citation",
        !           819:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           820: },
        !           821: { "code",      0, 0, 0, 0, 0, 0, 1, "computer code fragment",
        !           822:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           823: },
        !           824: { "col",       0, 2, 2, 1, 0, 0, 0, "table column ",
        !           825:        EMPTY , NULL , DECL col_attrs , NULL, NULL
        !           826: },
        !           827: { "colgroup",  0, 1, 0, 0, 0, 0, 0, "table column group ",
        !           828:        DECL col_elt , "col" , DECL col_attrs , NULL, NULL
        !           829: },
        !           830: { "dd",                0, 1, 0, 0, 0, 0, 0, "definition description ",
        !           831:        DECL html_flow , NULL , DECL html_attrs, NULL, NULL
        !           832: },
        !           833: { "del",       0, 0, 0, 0, 0, 0, 2, "deleted text ",
        !           834:        DECL html_flow , NULL , DECL edit_attrs , NULL, NULL
        !           835: },
        !           836: { "dfn",       0, 0, 0, 0, 0, 0, 1, "instance definition",
        !           837:        DECL html_inline , NULL , DECL html_attrs, NULL, NULL
        !           838: },
        !           839: { "dir",       0, 0, 0, 0, 1, 1, 0, "directory list",
        !           840:        DECL blockli_elt, "li" , NULL, DECL compact_attrs, NULL
        !           841: },
        !           842: { "div",       0, 0, 0, 0, 0, 0, 0, "generic language/style container",
        !           843:        DECL html_flow, NULL, DECL html_attrs, DECL align_attr, NULL
        !           844: },
        !           845: { "dl",                0, 0, 0, 0, 0, 0, 0, "definition list ",
        !           846:        DECL dl_contents , "dd" , DECL html_attrs, DECL compact_attr, NULL
        !           847: },
        !           848: { "dt",                0, 1, 0, 0, 0, 0, 0, "definition term ",
        !           849:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           850: },
        !           851: { "em",                0, 3, 0, 0, 0, 0, 1, "emphasis",
        !           852:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           853: },
        !           854: { "embed",     0, 1, 0, 0, 1, 1, 1, "generic embedded object ",
        !           855:        EMPTY, NULL, DECL embed_attrs, NULL, NULL
        !           856: },
        !           857: { "fieldset",  0, 0, 0, 0, 0, 0, 0, "form control group ",
        !           858:        DECL fieldset_contents , NULL, DECL html_attrs, NULL, NULL
        !           859: },
        !           860: { "font",      0, 3, 0, 0, 1, 1, 1, "local change to font ",
        !           861:        DECL html_inline, NULL, NULL, DECL font_attrs, NULL
        !           862: },
        !           863: { "form",      0, 0, 0, 0, 0, 0, 0, "interactive form ",
        !           864:        DECL form_contents, "fieldset", DECL form_attrs , DECL target_attr, DECL action_attr
        !           865: },
        !           866: { "frame",     0, 2, 2, 1, 0, 2, 0, "subwindow " ,
        !           867:        EMPTY, NULL, NULL, DECL frame_attrs, NULL
        !           868: },
        !           869: { "frameset",  0, 0, 0, 0, 0, 2, 0, "window subdivision" ,
        !           870:        DECL frameset_contents, "noframes" , NULL , DECL frameset_attrs, NULL
        !           871: },
        !           872: { "h1",                0, 0, 0, 0, 0, 0, 0, "heading ",
        !           873:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           874: },
        !           875: { "h2",                0, 0, 0, 0, 0, 0, 0, "heading ",
        !           876:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           877: },
        !           878: { "h3",                0, 0, 0, 0, 0, 0, 0, "heading ",
        !           879:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           880: },
        !           881: { "h4",                0, 0, 0, 0, 0, 0, 0, "heading ",
        !           882:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           883: },
        !           884: { "h5",                0, 0, 0, 0, 0, 0, 0, "heading ",
        !           885:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           886: },
        !           887: { "h6",                0, 0, 0, 0, 0, 0, 0, "heading ",
        !           888:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           889: },
        !           890: { "head",      1, 1, 0, 0, 0, 0, 0, "document head ",
        !           891:        DECL head_contents, NULL, DECL head_attrs, NULL, NULL
        !           892: },
        !           893: { "hr",                0, 2, 2, 1, 0, 0, 0, "horizontal rule " ,
        !           894:        EMPTY, NULL, DECL html_attrs, DECL hr_depr, NULL
        !           895: },
        !           896: { "html",      1, 1, 0, 0, 0, 0, 0, "document root element ",
        !           897:        DECL html_content , NULL , DECL i18n_attrs, DECL version_attr, NULL
        !           898: },
        !           899: { "i",         0, 3, 0, 0, 0, 0, 1, "italic text style",
        !           900:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           901: },
        !           902: { "iframe",    0, 0, 0, 0, 0, 1, 2, "inline subwindow ",
        !           903:        DECL html_flow, NULL, NULL, DECL iframe_attrs, NULL
        !           904: },
        !           905: { "img",       0, 2, 2, 1, 0, 0, 1, "embedded image ",
        !           906:        EMPTY, NULL, DECL img_attrs, DECL align_attr, DECL src_alt_attrs
        !           907: },
        !           908: { "input",     0, 2, 2, 1, 0, 0, 1, "form control ",
        !           909:        EMPTY, NULL, DECL input_attrs , DECL align_attr, NULL
        !           910: },
        !           911: { "ins",       0, 0, 0, 0, 0, 0, 2, "inserted text",
        !           912:        DECL html_flow, NULL, DECL edit_attrs, NULL, NULL
        !           913: },
        !           914: { "isindex",   0, 2, 2, 1, 1, 1, 0, "single line prompt ",
        !           915:        EMPTY, NULL, NULL, DECL prompt_attrs, NULL
        !           916: },
        !           917: { "kbd",       0, 0, 0, 0, 0, 0, 1, "text to be entered by the user",
        !           918:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           919: },
        !           920: { "label",     0, 0, 0, 0, 0, 0, 1, "form field label text ",
        !           921:        DECL html_inline MODIFIER, NULL, DECL label_attrs , NULL, NULL
        !           922: },
        !           923: { "legend",    0, 0, 0, 0, 0, 0, 0, "fieldset legend ",
        !           924:        DECL html_inline, NULL, DECL legend_attrs , DECL align_attr, NULL
        !           925: },
        !           926: { "li",                0, 1, 1, 0, 0, 0, 0, "list item ",
        !           927:        DECL html_flow, NULL, DECL html_attrs, NULL, NULL
        !           928: },
        !           929: { "link",      0, 2, 2, 1, 0, 0, 0, "a media-independent link ",
        !           930:        EMPTY, NULL, DECL link_attrs, DECL target_attr, NULL
        !           931: },
        !           932: { "map",       0, 0, 0, 0, 0, 0, 2, "client-side image map ",
        !           933:        DECL map_contents , NULL, DECL html_attrs , NULL, DECL name_attr
        !           934: },
        !           935: { "menu",      0, 0, 0, 0, 1, 1, 0, "menu list ",
        !           936:        DECL blockli_elt , NULL, NULL, DECL compact_attrs, NULL
        !           937: },
        !           938: { "meta",      0, 2, 2, 1, 0, 0, 0, "generic metainformation ",
        !           939:        EMPTY, NULL, DECL meta_attrs , NULL , DECL content_attr
        !           940: },
        !           941: { "noframes",  0, 0, 0, 0, 0, 2, 0, "alternate content container for non frame-based rendering ",
        !           942:        DECL noframes_content, "body" , DECL html_attrs, NULL, NULL
        !           943: },
        !           944: { "noscript",  0, 0, 0, 0, 0, 0, 0, "alternate content container for non script-based rendering ",
        !           945:        DECL html_flow, "div", DECL html_attrs, NULL, NULL
        !           946: },
        !           947: { "object",    0, 0, 0, 0, 0, 0, 2, "generic embedded object ",
        !           948:        DECL object_contents , "div" , DECL object_attrs, DECL object_depr, NULL
        !           949: },
        !           950: { "ol",                0, 0, 0, 0, 0, 0, 0, "ordered list ",
        !           951:        DECL li_elt , "li" , DECL html_attrs, DECL ol_attrs, NULL
        !           952: },
        !           953: { "optgroup",  0, 0, 0, 0, 0, 0, 0, "option group ",
        !           954:        DECL option_elt , "option", DECL optgroup_attrs, NULL, DECL label_attr
        !           955: },
        !           956: { "option",    0, 1, 0, 0, 0, 0, 0, "selectable choice " ,
        !           957:        DECL html_pcdata, NULL, DECL option_attrs, NULL, NULL
        !           958: },
        !           959: { "p",         0, 1, 0, 0, 0, 0, 0, "paragraph ",
        !           960:        DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL
        !           961: },
        !           962: { "param",     0, 2, 2, 1, 0, 0, 0, "named property value ",
        !           963:        EMPTY, NULL, DECL param_attrs, NULL, DECL name_attr
        !           964: },
        !           965: { "pre",       0, 0, 0, 0, 0, 0, 0, "preformatted text ",
        !           966:        DECL pre_content, NULL, DECL html_attrs, DECL width_attr, NULL
        !           967: },
        !           968: { "q",         0, 0, 0, 0, 0, 0, 1, "short inline quotation ",
        !           969:        DECL html_inline, NULL, DECL quote_attrs, NULL, NULL
        !           970: },
        !           971: { "s",         0, 3, 0, 0, 1, 1, 1, "strike-through text style",
        !           972:        DECL html_inline, NULL, NULL, DECL html_attrs, NULL
        !           973: },
        !           974: { "samp",      0, 0, 0, 0, 0, 0, 1, "sample program output, scripts, etc.",
        !           975:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           976: },
        !           977: { "script",    0, 0, 0, 0, 0, 0, 2, "script statements ",
        !           978:        DECL html_cdata, NULL, DECL script_attrs, DECL language_attr, DECL type_attr
        !           979: },
        !           980: { "select",    0, 0, 0, 0, 0, 0, 1, "option selector ",
        !           981:        DECL select_content, NULL, DECL select_attrs, NULL, NULL
        !           982: },
        !           983: { "small",     0, 3, 0, 0, 0, 0, 1, "small text style",
        !           984:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           985: },
        !           986: { "span",      0, 0, 0, 0, 0, 0, 1, "generic language/style container ",
        !           987:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           988: },
        !           989: { "strike",    0, 3, 0, 0, 1, 1, 1, "strike-through text",
        !           990:        DECL html_inline, NULL, NULL, DECL html_attrs, NULL
        !           991: },
        !           992: { "strong",    0, 3, 0, 0, 0, 0, 1, "strong emphasis",
        !           993:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !           994: },
        !           995: { "style",     0, 0, 0, 0, 0, 0, 0, "style info ",
        !           996:        DECL html_cdata, NULL, DECL style_attrs, NULL, DECL type_attr
        !           997: },
        !           998: { "sub",       0, 3, 0, 0, 0, 0, 1, "subscript",
        !           999:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !          1000: },
        !          1001: { "sup",       0, 3, 0, 0, 0, 0, 1, "superscript ",
        !          1002:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !          1003: },
        !          1004: { "table",     0, 0, 0, 0, 0, 0, 0, "",
        !          1005:        DECL table_contents , "tr" , DECL table_attrs , DECL table_depr, NULL
        !          1006: },
        !          1007: { "tbody",     1, 0, 0, 0, 0, 0, 0, "table body ",
        !          1008:        DECL tr_elt , "tr" , DECL talign_attrs, NULL, NULL
        !          1009: },
        !          1010: { "td",                0, 0, 0, 0, 0, 0, 0, "table data cell",
        !          1011:        DECL html_flow, NULL, DECL th_td_attr, DECL th_td_depr, NULL
        !          1012: },
        !          1013: { "textarea",  0, 0, 0, 0, 0, 0, 1, "multi-line text field ",
        !          1014:        DECL html_pcdata, NULL, DECL textarea_attrs, NULL, DECL rows_cols_attr
        !          1015: },
        !          1016: { "tfoot",     0, 1, 0, 0, 0, 0, 0, "table footer ",
        !          1017:        DECL tr_elt , "tr" , DECL talign_attrs, NULL, NULL
        !          1018: },
        !          1019: { "th",                0, 1, 0, 0, 0, 0, 0, "table header cell",
        !          1020:        DECL html_flow, NULL, DECL th_td_attr, DECL th_td_depr, NULL
        !          1021: },
        !          1022: { "thead",     0, 1, 0, 0, 0, 0, 0, "table header ",
        !          1023:        DECL tr_elt , "tr" , DECL talign_attrs, NULL, NULL
        !          1024: },
        !          1025: { "title",     0, 0, 0, 0, 0, 0, 0, "document title ",
        !          1026:        DECL html_pcdata, NULL, DECL i18n_attrs, NULL, NULL
        !          1027: },
        !          1028: { "tr",                0, 0, 0, 0, 0, 0, 0, "table row ",
        !          1029:        DECL tr_contents , "td" , DECL talign_attrs, DECL bgcolor_attr, NULL
        !          1030: },
        !          1031: { "tt",                0, 3, 0, 0, 0, 0, 1, "teletype or monospaced text style",
        !          1032:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !          1033: },
        !          1034: { "u",         0, 3, 0, 0, 1, 1, 1, "underlined text style",
        !          1035:        DECL html_inline, NULL, NULL, DECL html_attrs, NULL
        !          1036: },
        !          1037: { "ul",                0, 0, 0, 0, 0, 0, 0, "unordered list ",
        !          1038:        DECL li_elt , "li" , DECL html_attrs, DECL ul_depr, NULL
        !          1039: },
        !          1040: { "var",       0, 0, 0, 0, 0, 0, 1, "instance of a variable or program argument",
        !          1041:        DECL html_inline, NULL, DECL html_attrs, NULL, NULL
        !          1042: }
        !          1043: };
        !          1044: 
        !          1045: /*
        !          1046:  * start tags that imply the end of current element
        !          1047:  */
        !          1048: static const char * const htmlStartClose[] = {
        !          1049: "form",                "form", "p", "hr", "h1", "h2", "h3", "h4", "h5", "h6",
        !          1050:                "dl", "ul", "ol", "menu", "dir", "address", "pre",
        !          1051:                "listing", "xmp", "head", NULL,
        !          1052: "head",                "p", NULL,
        !          1053: "title",       "p", NULL,
        !          1054: "body",                "head", "style", "link", "title", "p", NULL,
        !          1055: "frameset",    "head", "style", "link", "title", "p", NULL,
        !          1056: "li",          "p", "h1", "h2", "h3", "h4", "h5", "h6", "dl", "address",
        !          1057:                "pre", "listing", "xmp", "head", "li", NULL,
        !          1058: "hr",          "p", "head", NULL,
        !          1059: "h1",          "p", "head", NULL,
        !          1060: "h2",          "p", "head", NULL,
        !          1061: "h3",          "p", "head", NULL,
        !          1062: "h4",          "p", "head", NULL,
        !          1063: "h5",          "p", "head", NULL,
        !          1064: "h6",          "p", "head", NULL,
        !          1065: "dir",         "p", "head", NULL,
        !          1066: "address",     "p", "head", "ul", NULL,
        !          1067: "pre",         "p", "head", "ul", NULL,
        !          1068: "listing",     "p", "head", NULL,
        !          1069: "xmp",         "p", "head", NULL,
        !          1070: "blockquote",  "p", "head", NULL,
        !          1071: "dl",          "p", "dt", "menu", "dir", "address", "pre", "listing",
        !          1072:                "xmp", "head", NULL,
        !          1073: "dt",          "p", "menu", "dir", "address", "pre", "listing", "xmp",
        !          1074:                 "head", "dd", NULL,
        !          1075: "dd",          "p", "menu", "dir", "address", "pre", "listing", "xmp",
        !          1076:                 "head", "dt", NULL,
        !          1077: "ul",          "p", "head", "ol", "menu", "dir", "address", "pre",
        !          1078:                "listing", "xmp", NULL,
        !          1079: "ol",          "p", "head", "ul", NULL,
        !          1080: "menu",                "p", "head", "ul", NULL,
        !          1081: "p",           "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL,
        !          1082: "div",         "p", "head", NULL,
        !          1083: "noscript",    "p", "head", NULL,
        !          1084: "center",      "font", "b", "i", "p", "head", NULL,
        !          1085: "a",           "a", NULL,
        !          1086: "caption",     "p", NULL,
        !          1087: "colgroup",    "caption", "colgroup", "col", "p", NULL,
        !          1088: "col",         "caption", "col", "p", NULL,
        !          1089: "table",       "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", "pre",
        !          1090:                "listing", "xmp", "a", NULL,
        !          1091: "th",          "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL,
        !          1092: "td",          "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL,
        !          1093: "tr",          "th", "td", "tr", "caption", "col", "colgroup", "p", NULL,
        !          1094: "thead",       "caption", "col", "colgroup", NULL,
        !          1095: "tfoot",       "th", "td", "tr", "caption", "col", "colgroup", "thead",
        !          1096:                "tbody", "p", NULL,
        !          1097: "tbody",       "th", "td", "tr", "caption", "col", "colgroup", "thead",
        !          1098:                "tfoot", "tbody", "p", NULL,
        !          1099: "optgroup",    "option", NULL,
        !          1100: "option",      "option", NULL,
        !          1101: "fieldset",    "legend", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6",
        !          1102:                "pre", "listing", "xmp", "a", NULL,
        !          1103: NULL
        !          1104: };
        !          1105: 
        !          1106: /*
        !          1107:  * The list of HTML elements which are supposed not to have
        !          1108:  * CDATA content and where a p element will be implied
        !          1109:  *
        !          1110:  * TODO: extend that list by reading the HTML SGML DTD on
        !          1111:  *       implied paragraph
        !          1112:  */
        !          1113: static const char *const htmlNoContentElements[] = {
        !          1114:     "html",
        !          1115:     "head",
        !          1116:     NULL
        !          1117: };
        !          1118: 
        !          1119: /*
        !          1120:  * The list of HTML attributes which are of content %Script;
        !          1121:  * NOTE: when adding ones, check htmlIsScriptAttribute() since
        !          1122:  *       it assumes the name starts with 'on'
        !          1123:  */
        !          1124: static const char *const htmlScriptAttributes[] = {
        !          1125:     "onclick",
        !          1126:     "ondblclick",
        !          1127:     "onmousedown",
        !          1128:     "onmouseup",
        !          1129:     "onmouseover",
        !          1130:     "onmousemove",
        !          1131:     "onmouseout",
        !          1132:     "onkeypress",
        !          1133:     "onkeydown",
        !          1134:     "onkeyup",
        !          1135:     "onload",
        !          1136:     "onunload",
        !          1137:     "onfocus",
        !          1138:     "onblur",
        !          1139:     "onsubmit",
        !          1140:     "onrest",
        !          1141:     "onchange",
        !          1142:     "onselect"
        !          1143: };
        !          1144: 
        !          1145: /*
        !          1146:  * This table is used by the htmlparser to know what to do with
        !          1147:  * broken html pages. By assigning different priorities to different
        !          1148:  * elements the parser can decide how to handle extra endtags.
        !          1149:  * Endtags are only allowed to close elements with lower or equal
        !          1150:  * priority.
        !          1151:  */
        !          1152: 
        !          1153: typedef struct {
        !          1154:     const char *name;
        !          1155:     int priority;
        !          1156: } elementPriority;
        !          1157: 
        !          1158: static const elementPriority htmlEndPriority[] = {
        !          1159:     {"div",   150},
        !          1160:     {"td",    160},
        !          1161:     {"th",    160},
        !          1162:     {"tr",    170},
        !          1163:     {"thead", 180},
        !          1164:     {"tbody", 180},
        !          1165:     {"tfoot", 180},
        !          1166:     {"table", 190},
        !          1167:     {"head",  200},
        !          1168:     {"body",  200},
        !          1169:     {"html",  220},
        !          1170:     {NULL,    100} /* Default priority */
        !          1171: };
        !          1172: 
        !          1173: static const char** htmlStartCloseIndex[100];
        !          1174: static int htmlStartCloseIndexinitialized = 0;
        !          1175: 
        !          1176: /************************************************************************
        !          1177:  *                                                                     *
        !          1178:  *     functions to handle HTML specific data                  *
        !          1179:  *                                                                     *
        !          1180:  ************************************************************************/
        !          1181: 
        !          1182: /**
        !          1183:  * htmlInitAutoClose:
        !          1184:  *
        !          1185:  * Initialize the htmlStartCloseIndex for fast lookup of closing tags names.
        !          1186:  * This is not reentrant. Call xmlInitParser() once before processing in
        !          1187:  * case of use in multithreaded programs.
        !          1188:  */
        !          1189: void
        !          1190: htmlInitAutoClose(void) {
        !          1191:     int indx, i = 0;
        !          1192: 
        !          1193:     if (htmlStartCloseIndexinitialized) return;
        !          1194: 
        !          1195:     for (indx = 0;indx < 100;indx ++) htmlStartCloseIndex[indx] = NULL;
        !          1196:     indx = 0;
        !          1197:     while ((htmlStartClose[i] != NULL) && (indx < 100 - 1)) {
        !          1198:         htmlStartCloseIndex[indx++] = (const char**) &htmlStartClose[i];
        !          1199:        while (htmlStartClose[i] != NULL) i++;
        !          1200:        i++;
        !          1201:     }
        !          1202:     htmlStartCloseIndexinitialized = 1;
        !          1203: }
        !          1204: 
        !          1205: /**
        !          1206:  * htmlTagLookup:
        !          1207:  * @tag:  The tag name in lowercase
        !          1208:  *
        !          1209:  * Lookup the HTML tag in the ElementTable
        !          1210:  *
        !          1211:  * Returns the related htmlElemDescPtr or NULL if not found.
        !          1212:  */
        !          1213: const htmlElemDesc *
        !          1214: htmlTagLookup(const xmlChar *tag) {
        !          1215:     unsigned int i;
        !          1216: 
        !          1217:     for (i = 0; i < (sizeof(html40ElementTable) /
        !          1218:                      sizeof(html40ElementTable[0]));i++) {
        !          1219:         if (!xmlStrcasecmp(tag, BAD_CAST html40ElementTable[i].name))
        !          1220:            return((htmlElemDescPtr) &html40ElementTable[i]);
        !          1221:     }
        !          1222:     return(NULL);
        !          1223: }
        !          1224: 
        !          1225: /**
        !          1226:  * htmlGetEndPriority:
        !          1227:  * @name: The name of the element to look up the priority for.
        !          1228:  *
        !          1229:  * Return value: The "endtag" priority.
        !          1230:  **/
        !          1231: static int
        !          1232: htmlGetEndPriority (const xmlChar *name) {
        !          1233:     int i = 0;
        !          1234: 
        !          1235:     while ((htmlEndPriority[i].name != NULL) &&
        !          1236:           (!xmlStrEqual((const xmlChar *)htmlEndPriority[i].name, name)))
        !          1237:        i++;
        !          1238: 
        !          1239:     return(htmlEndPriority[i].priority);
        !          1240: }
        !          1241: 
        !          1242: 
        !          1243: /**
        !          1244:  * htmlCheckAutoClose:
        !          1245:  * @newtag:  The new tag name
        !          1246:  * @oldtag:  The old tag name
        !          1247:  *
        !          1248:  * Checks whether the new tag is one of the registered valid tags for
        !          1249:  * closing old.
        !          1250:  * Initialize the htmlStartCloseIndex for fast lookup of closing tags names.
        !          1251:  *
        !          1252:  * Returns 0 if no, 1 if yes.
        !          1253:  */
        !          1254: static int
        !          1255: htmlCheckAutoClose(const xmlChar * newtag, const xmlChar * oldtag)
        !          1256: {
        !          1257:     int i, indx;
        !          1258:     const char **closed = NULL;
        !          1259: 
        !          1260:     if (htmlStartCloseIndexinitialized == 0)
        !          1261:         htmlInitAutoClose();
        !          1262: 
        !          1263:     /* inefficient, but not a big deal */
        !          1264:     for (indx = 0; indx < 100; indx++) {
        !          1265:         closed = htmlStartCloseIndex[indx];
        !          1266:         if (closed == NULL)
        !          1267:             return (0);
        !          1268:         if (xmlStrEqual(BAD_CAST * closed, newtag))
        !          1269:             break;
        !          1270:     }
        !          1271: 
        !          1272:     i = closed - htmlStartClose;
        !          1273:     i++;
        !          1274:     while (htmlStartClose[i] != NULL) {
        !          1275:         if (xmlStrEqual(BAD_CAST htmlStartClose[i], oldtag)) {
        !          1276:             return (1);
        !          1277:         }
        !          1278:         i++;
        !          1279:     }
        !          1280:     return (0);
        !          1281: }
        !          1282: 
        !          1283: /**
        !          1284:  * htmlAutoCloseOnClose:
        !          1285:  * @ctxt:  an HTML parser context
        !          1286:  * @newtag:  The new tag name
        !          1287:  * @force:  force the tag closure
        !          1288:  *
        !          1289:  * The HTML DTD allows an ending tag to implicitly close other tags.
        !          1290:  */
        !          1291: static void
        !          1292: htmlAutoCloseOnClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag)
        !          1293: {
        !          1294:     const htmlElemDesc *info;
        !          1295:     int i, priority;
        !          1296: 
        !          1297:     priority = htmlGetEndPriority(newtag);
        !          1298: 
        !          1299:     for (i = (ctxt->nameNr - 1); i >= 0; i--) {
        !          1300: 
        !          1301:         if (xmlStrEqual(newtag, ctxt->nameTab[i]))
        !          1302:             break;
        !          1303:         /*
        !          1304:          * A missplaced endtag can only close elements with lower
        !          1305:          * or equal priority, so if we find an element with higher
        !          1306:          * priority before we find an element with
        !          1307:          * matching name, we just ignore this endtag
        !          1308:          */
        !          1309:         if (htmlGetEndPriority(ctxt->nameTab[i]) > priority)
        !          1310:             return;
        !          1311:     }
        !          1312:     if (i < 0)
        !          1313:         return;
        !          1314: 
        !          1315:     while (!xmlStrEqual(newtag, ctxt->name)) {
        !          1316:         info = htmlTagLookup(ctxt->name);
        !          1317:         if ((info != NULL) && (info->endTag == 3)) {
        !          1318:             htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
        !          1319:                         "Opening and ending tag mismatch: %s and %s\n",
        !          1320:                         newtag, ctxt->name);
        !          1321:         }
        !          1322:         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          1323:             ctxt->sax->endElement(ctxt->userData, ctxt->name);
        !          1324:        htmlnamePop(ctxt);
        !          1325:     }
        !          1326: }
        !          1327: 
        !          1328: /**
        !          1329:  * htmlAutoCloseOnEnd:
        !          1330:  * @ctxt:  an HTML parser context
        !          1331:  *
        !          1332:  * Close all remaining tags at the end of the stream
        !          1333:  */
        !          1334: static void
        !          1335: htmlAutoCloseOnEnd(htmlParserCtxtPtr ctxt)
        !          1336: {
        !          1337:     int i;
        !          1338: 
        !          1339:     if (ctxt->nameNr == 0)
        !          1340:         return;
        !          1341:     for (i = (ctxt->nameNr - 1); i >= 0; i--) {
        !          1342:         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          1343:             ctxt->sax->endElement(ctxt->userData, ctxt->name);
        !          1344:        htmlnamePop(ctxt);
        !          1345:     }
        !          1346: }
        !          1347: 
        !          1348: /**
        !          1349:  * htmlAutoClose:
        !          1350:  * @ctxt:  an HTML parser context
        !          1351:  * @newtag:  The new tag name or NULL
        !          1352:  *
        !          1353:  * The HTML DTD allows a tag to implicitly close other tags.
        !          1354:  * The list is kept in htmlStartClose array. This function is
        !          1355:  * called when a new tag has been detected and generates the
        !          1356:  * appropriates closes if possible/needed.
        !          1357:  * If newtag is NULL this mean we are at the end of the resource
        !          1358:  * and we should check
        !          1359:  */
        !          1360: static void
        !          1361: htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag)
        !          1362: {
        !          1363:     while ((newtag != NULL) && (ctxt->name != NULL) &&
        !          1364:            (htmlCheckAutoClose(newtag, ctxt->name))) {
        !          1365:         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          1366:             ctxt->sax->endElement(ctxt->userData, ctxt->name);
        !          1367:        htmlnamePop(ctxt);
        !          1368:     }
        !          1369:     if (newtag == NULL) {
        !          1370:         htmlAutoCloseOnEnd(ctxt);
        !          1371:         return;
        !          1372:     }
        !          1373:     while ((newtag == NULL) && (ctxt->name != NULL) &&
        !          1374:            ((xmlStrEqual(ctxt->name, BAD_CAST "head")) ||
        !          1375:             (xmlStrEqual(ctxt->name, BAD_CAST "body")) ||
        !          1376:             (xmlStrEqual(ctxt->name, BAD_CAST "html")))) {
        !          1377:         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          1378:             ctxt->sax->endElement(ctxt->userData, ctxt->name);
        !          1379:        htmlnamePop(ctxt);
        !          1380:     }
        !          1381: }
        !          1382: 
        !          1383: /**
        !          1384:  * htmlAutoCloseTag:
        !          1385:  * @doc:  the HTML document
        !          1386:  * @name:  The tag name
        !          1387:  * @elem:  the HTML element
        !          1388:  *
        !          1389:  * The HTML DTD allows a tag to implicitly close other tags.
        !          1390:  * The list is kept in htmlStartClose array. This function checks
        !          1391:  * if the element or one of it's children would autoclose the
        !          1392:  * given tag.
        !          1393:  *
        !          1394:  * Returns 1 if autoclose, 0 otherwise
        !          1395:  */
        !          1396: int
        !          1397: htmlAutoCloseTag(htmlDocPtr doc, const xmlChar *name, htmlNodePtr elem) {
        !          1398:     htmlNodePtr child;
        !          1399: 
        !          1400:     if (elem == NULL) return(1);
        !          1401:     if (xmlStrEqual(name, elem->name)) return(0);
        !          1402:     if (htmlCheckAutoClose(elem->name, name)) return(1);
        !          1403:     child = elem->children;
        !          1404:     while (child != NULL) {
        !          1405:         if (htmlAutoCloseTag(doc, name, child)) return(1);
        !          1406:        child = child->next;
        !          1407:     }
        !          1408:     return(0);
        !          1409: }
        !          1410: 
        !          1411: /**
        !          1412:  * htmlIsAutoClosed:
        !          1413:  * @doc:  the HTML document
        !          1414:  * @elem:  the HTML element
        !          1415:  *
        !          1416:  * The HTML DTD allows a tag to implicitly close other tags.
        !          1417:  * The list is kept in htmlStartClose array. This function checks
        !          1418:  * if a tag is autoclosed by one of it's child
        !          1419:  *
        !          1420:  * Returns 1 if autoclosed, 0 otherwise
        !          1421:  */
        !          1422: int
        !          1423: htmlIsAutoClosed(htmlDocPtr doc, htmlNodePtr elem) {
        !          1424:     htmlNodePtr child;
        !          1425: 
        !          1426:     if (elem == NULL) return(1);
        !          1427:     child = elem->children;
        !          1428:     while (child != NULL) {
        !          1429:        if (htmlAutoCloseTag(doc, elem->name, child)) return(1);
        !          1430:        child = child->next;
        !          1431:     }
        !          1432:     return(0);
        !          1433: }
        !          1434: 
        !          1435: /**
        !          1436:  * htmlCheckImplied:
        !          1437:  * @ctxt:  an HTML parser context
        !          1438:  * @newtag:  The new tag name
        !          1439:  *
        !          1440:  * The HTML DTD allows a tag to exists only implicitly
        !          1441:  * called when a new tag has been detected and generates the
        !          1442:  * appropriates implicit tags if missing
        !          1443:  */
        !          1444: static void
        !          1445: htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) {
        !          1446:     int i;
        !          1447: 
        !          1448:     if (ctxt->options & HTML_PARSE_NOIMPLIED)
        !          1449:         return;
        !          1450:     if (!htmlOmittedDefaultValue)
        !          1451:        return;
        !          1452:     if (xmlStrEqual(newtag, BAD_CAST"html"))
        !          1453:        return;
        !          1454:     if (ctxt->nameNr <= 0) {
        !          1455:        htmlnamePush(ctxt, BAD_CAST"html");
        !          1456:        if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
        !          1457:            ctxt->sax->startElement(ctxt->userData, BAD_CAST"html", NULL);
        !          1458:     }
        !          1459:     if ((xmlStrEqual(newtag, BAD_CAST"body")) || (xmlStrEqual(newtag, BAD_CAST"head")))
        !          1460:         return;
        !          1461:     if ((ctxt->nameNr <= 1) &&
        !          1462:         ((xmlStrEqual(newtag, BAD_CAST"script")) ||
        !          1463:         (xmlStrEqual(newtag, BAD_CAST"style")) ||
        !          1464:         (xmlStrEqual(newtag, BAD_CAST"meta")) ||
        !          1465:         (xmlStrEqual(newtag, BAD_CAST"link")) ||
        !          1466:         (xmlStrEqual(newtag, BAD_CAST"title")) ||
        !          1467:         (xmlStrEqual(newtag, BAD_CAST"base")))) {
        !          1468:         if (ctxt->html >= 3) {
        !          1469:             /* we already saw or generated an <head> before */
        !          1470:             return;
        !          1471:         }
        !          1472:         /*
        !          1473:          * dropped OBJECT ... i you put it first BODY will be
        !          1474:          * assumed !
        !          1475:          */
        !          1476:         htmlnamePush(ctxt, BAD_CAST"head");
        !          1477:         if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
        !          1478:             ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
        !          1479:     } else if ((!xmlStrEqual(newtag, BAD_CAST"noframes")) &&
        !          1480:               (!xmlStrEqual(newtag, BAD_CAST"frame")) &&
        !          1481:               (!xmlStrEqual(newtag, BAD_CAST"frameset"))) {
        !          1482:         if (ctxt->html >= 10) {
        !          1483:             /* we already saw or generated a <body> before */
        !          1484:             return;
        !          1485:         }
        !          1486:        for (i = 0;i < ctxt->nameNr;i++) {
        !          1487:            if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"body")) {
        !          1488:                return;
        !          1489:            }
        !          1490:            if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"head")) {
        !          1491:                return;
        !          1492:            }
        !          1493:        }
        !          1494: 
        !          1495:        htmlnamePush(ctxt, BAD_CAST"body");
        !          1496:        if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
        !          1497:            ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
        !          1498:     }
        !          1499: }
        !          1500: 
        !          1501: /**
        !          1502:  * htmlCheckParagraph
        !          1503:  * @ctxt:  an HTML parser context
        !          1504:  *
        !          1505:  * Check whether a p element need to be implied before inserting
        !          1506:  * characters in the current element.
        !          1507:  *
        !          1508:  * Returns 1 if a paragraph has been inserted, 0 if not and -1
        !          1509:  *         in case of error.
        !          1510:  */
        !          1511: 
        !          1512: static int
        !          1513: htmlCheckParagraph(htmlParserCtxtPtr ctxt) {
        !          1514:     const xmlChar *tag;
        !          1515:     int i;
        !          1516: 
        !          1517:     if (ctxt == NULL)
        !          1518:        return(-1);
        !          1519:     tag = ctxt->name;
        !          1520:     if (tag == NULL) {
        !          1521:        htmlAutoClose(ctxt, BAD_CAST"p");
        !          1522:        htmlCheckImplied(ctxt, BAD_CAST"p");
        !          1523:        htmlnamePush(ctxt, BAD_CAST"p");
        !          1524:        if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
        !          1525:            ctxt->sax->startElement(ctxt->userData, BAD_CAST"p", NULL);
        !          1526:        return(1);
        !          1527:     }
        !          1528:     if (!htmlOmittedDefaultValue)
        !          1529:        return(0);
        !          1530:     for (i = 0; htmlNoContentElements[i] != NULL; i++) {
        !          1531:        if (xmlStrEqual(tag, BAD_CAST htmlNoContentElements[i])) {
        !          1532:            htmlAutoClose(ctxt, BAD_CAST"p");
        !          1533:            htmlCheckImplied(ctxt, BAD_CAST"p");
        !          1534:            htmlnamePush(ctxt, BAD_CAST"p");
        !          1535:            if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
        !          1536:                ctxt->sax->startElement(ctxt->userData, BAD_CAST"p", NULL);
        !          1537:            return(1);
        !          1538:        }
        !          1539:     }
        !          1540:     return(0);
        !          1541: }
        !          1542: 
        !          1543: /**
        !          1544:  * htmlIsScriptAttribute:
        !          1545:  * @name:  an attribute name
        !          1546:  *
        !          1547:  * Check if an attribute is of content type Script
        !          1548:  *
        !          1549:  * Returns 1 is the attribute is a script 0 otherwise
        !          1550:  */
        !          1551: int
        !          1552: htmlIsScriptAttribute(const xmlChar *name) {
        !          1553:     unsigned int i;
        !          1554: 
        !          1555:     if (name == NULL)
        !          1556:       return(0);
        !          1557:     /*
        !          1558:      * all script attributes start with 'on'
        !          1559:      */
        !          1560:     if ((name[0] != 'o') || (name[1] != 'n'))
        !          1561:       return(0);
        !          1562:     for (i = 0;
        !          1563:         i < sizeof(htmlScriptAttributes)/sizeof(htmlScriptAttributes[0]);
        !          1564:         i++) {
        !          1565:        if (xmlStrEqual(name, (const xmlChar *) htmlScriptAttributes[i]))
        !          1566:            return(1);
        !          1567:     }
        !          1568:     return(0);
        !          1569: }
        !          1570: 
        !          1571: /************************************************************************
        !          1572:  *                                                                     *
        !          1573:  *     The list of HTML predefined entities                    *
        !          1574:  *                                                                     *
        !          1575:  ************************************************************************/
        !          1576: 
        !          1577: 
        !          1578: static const htmlEntityDesc  html40EntitiesTable[] = {
        !          1579: /*
        !          1580:  * the 4 absolute ones, plus apostrophe.
        !          1581:  */
        !          1582: { 34,  "quot", "quotation mark = APL quote, U+0022 ISOnum" },
        !          1583: { 38,  "amp",  "ampersand, U+0026 ISOnum" },
        !          1584: { 39,  "apos", "single quote" },
        !          1585: { 60,  "lt",   "less-than sign, U+003C ISOnum" },
        !          1586: { 62,  "gt",   "greater-than sign, U+003E ISOnum" },
        !          1587: 
        !          1588: /*
        !          1589:  * A bunch still in the 128-255 range
        !          1590:  * Replacing them depend really on the charset used.
        !          1591:  */
        !          1592: { 160, "nbsp", "no-break space = non-breaking space, U+00A0 ISOnum" },
        !          1593: { 161, "iexcl","inverted exclamation mark, U+00A1 ISOnum" },
        !          1594: { 162, "cent", "cent sign, U+00A2 ISOnum" },
        !          1595: { 163, "pound","pound sign, U+00A3 ISOnum" },
        !          1596: { 164, "curren","currency sign, U+00A4 ISOnum" },
        !          1597: { 165, "yen",  "yen sign = yuan sign, U+00A5 ISOnum" },
        !          1598: { 166, "brvbar","broken bar = broken vertical bar, U+00A6 ISOnum" },
        !          1599: { 167, "sect", "section sign, U+00A7 ISOnum" },
        !          1600: { 168, "uml",  "diaeresis = spacing diaeresis, U+00A8 ISOdia" },
        !          1601: { 169, "copy", "copyright sign, U+00A9 ISOnum" },
        !          1602: { 170, "ordf", "feminine ordinal indicator, U+00AA ISOnum" },
        !          1603: { 171, "laquo","left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum" },
        !          1604: { 172, "not",  "not sign, U+00AC ISOnum" },
        !          1605: { 173, "shy",  "soft hyphen = discretionary hyphen, U+00AD ISOnum" },
        !          1606: { 174, "reg",  "registered sign = registered trade mark sign, U+00AE ISOnum" },
        !          1607: { 175, "macr", "macron = spacing macron = overline = APL overbar, U+00AF ISOdia" },
        !          1608: { 176, "deg",  "degree sign, U+00B0 ISOnum" },
        !          1609: { 177, "plusmn","plus-minus sign = plus-or-minus sign, U+00B1 ISOnum" },
        !          1610: { 178, "sup2", "superscript two = superscript digit two = squared, U+00B2 ISOnum" },
        !          1611: { 179, "sup3", "superscript three = superscript digit three = cubed, U+00B3 ISOnum" },
        !          1612: { 180, "acute","acute accent = spacing acute, U+00B4 ISOdia" },
        !          1613: { 181, "micro","micro sign, U+00B5 ISOnum" },
        !          1614: { 182, "para", "pilcrow sign = paragraph sign, U+00B6 ISOnum" },
        !          1615: { 183, "middot","middle dot = Georgian comma Greek middle dot, U+00B7 ISOnum" },
        !          1616: { 184, "cedil","cedilla = spacing cedilla, U+00B8 ISOdia" },
        !          1617: { 185, "sup1", "superscript one = superscript digit one, U+00B9 ISOnum" },
        !          1618: { 186, "ordm", "masculine ordinal indicator, U+00BA ISOnum" },
        !          1619: { 187, "raquo","right-pointing double angle quotation mark right pointing guillemet, U+00BB ISOnum" },
        !          1620: { 188, "frac14","vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum" },
        !          1621: { 189, "frac12","vulgar fraction one half = fraction one half, U+00BD ISOnum" },
        !          1622: { 190, "frac34","vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum" },
        !          1623: { 191, "iquest","inverted question mark = turned question mark, U+00BF ISOnum" },
        !          1624: { 192, "Agrave","latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1" },
        !          1625: { 193, "Aacute","latin capital letter A with acute, U+00C1 ISOlat1" },
        !          1626: { 194, "Acirc","latin capital letter A with circumflex, U+00C2 ISOlat1" },
        !          1627: { 195, "Atilde","latin capital letter A with tilde, U+00C3 ISOlat1" },
        !          1628: { 196, "Auml", "latin capital letter A with diaeresis, U+00C4 ISOlat1" },
        !          1629: { 197, "Aring","latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1" },
        !          1630: { 198, "AElig","latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1" },
        !          1631: { 199, "Ccedil","latin capital letter C with cedilla, U+00C7 ISOlat1" },
        !          1632: { 200, "Egrave","latin capital letter E with grave, U+00C8 ISOlat1" },
        !          1633: { 201, "Eacute","latin capital letter E with acute, U+00C9 ISOlat1" },
        !          1634: { 202, "Ecirc","latin capital letter E with circumflex, U+00CA ISOlat1" },
        !          1635: { 203, "Euml", "latin capital letter E with diaeresis, U+00CB ISOlat1" },
        !          1636: { 204, "Igrave","latin capital letter I with grave, U+00CC ISOlat1" },
        !          1637: { 205, "Iacute","latin capital letter I with acute, U+00CD ISOlat1" },
        !          1638: { 206, "Icirc","latin capital letter I with circumflex, U+00CE ISOlat1" },
        !          1639: { 207, "Iuml", "latin capital letter I with diaeresis, U+00CF ISOlat1" },
        !          1640: { 208, "ETH",  "latin capital letter ETH, U+00D0 ISOlat1" },
        !          1641: { 209, "Ntilde","latin capital letter N with tilde, U+00D1 ISOlat1" },
        !          1642: { 210, "Ograve","latin capital letter O with grave, U+00D2 ISOlat1" },
        !          1643: { 211, "Oacute","latin capital letter O with acute, U+00D3 ISOlat1" },
        !          1644: { 212, "Ocirc","latin capital letter O with circumflex, U+00D4 ISOlat1" },
        !          1645: { 213, "Otilde","latin capital letter O with tilde, U+00D5 ISOlat1" },
        !          1646: { 214, "Ouml", "latin capital letter O with diaeresis, U+00D6 ISOlat1" },
        !          1647: { 215, "times","multiplication sign, U+00D7 ISOnum" },
        !          1648: { 216, "Oslash","latin capital letter O with stroke latin capital letter O slash, U+00D8 ISOlat1" },
        !          1649: { 217, "Ugrave","latin capital letter U with grave, U+00D9 ISOlat1" },
        !          1650: { 218, "Uacute","latin capital letter U with acute, U+00DA ISOlat1" },
        !          1651: { 219, "Ucirc","latin capital letter U with circumflex, U+00DB ISOlat1" },
        !          1652: { 220, "Uuml", "latin capital letter U with diaeresis, U+00DC ISOlat1" },
        !          1653: { 221, "Yacute","latin capital letter Y with acute, U+00DD ISOlat1" },
        !          1654: { 222, "THORN","latin capital letter THORN, U+00DE ISOlat1" },
        !          1655: { 223, "szlig","latin small letter sharp s = ess-zed, U+00DF ISOlat1" },
        !          1656: { 224, "agrave","latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1" },
        !          1657: { 225, "aacute","latin small letter a with acute, U+00E1 ISOlat1" },
        !          1658: { 226, "acirc","latin small letter a with circumflex, U+00E2 ISOlat1" },
        !          1659: { 227, "atilde","latin small letter a with tilde, U+00E3 ISOlat1" },
        !          1660: { 228, "auml", "latin small letter a with diaeresis, U+00E4 ISOlat1" },
        !          1661: { 229, "aring","latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1" },
        !          1662: { 230, "aelig","latin small letter ae = latin small ligature ae, U+00E6 ISOlat1" },
        !          1663: { 231, "ccedil","latin small letter c with cedilla, U+00E7 ISOlat1" },
        !          1664: { 232, "egrave","latin small letter e with grave, U+00E8 ISOlat1" },
        !          1665: { 233, "eacute","latin small letter e with acute, U+00E9 ISOlat1" },
        !          1666: { 234, "ecirc","latin small letter e with circumflex, U+00EA ISOlat1" },
        !          1667: { 235, "euml", "latin small letter e with diaeresis, U+00EB ISOlat1" },
        !          1668: { 236, "igrave","latin small letter i with grave, U+00EC ISOlat1" },
        !          1669: { 237, "iacute","latin small letter i with acute, U+00ED ISOlat1" },
        !          1670: { 238, "icirc","latin small letter i with circumflex, U+00EE ISOlat1" },
        !          1671: { 239, "iuml", "latin small letter i with diaeresis, U+00EF ISOlat1" },
        !          1672: { 240, "eth",  "latin small letter eth, U+00F0 ISOlat1" },
        !          1673: { 241, "ntilde","latin small letter n with tilde, U+00F1 ISOlat1" },
        !          1674: { 242, "ograve","latin small letter o with grave, U+00F2 ISOlat1" },
        !          1675: { 243, "oacute","latin small letter o with acute, U+00F3 ISOlat1" },
        !          1676: { 244, "ocirc","latin small letter o with circumflex, U+00F4 ISOlat1" },
        !          1677: { 245, "otilde","latin small letter o with tilde, U+00F5 ISOlat1" },
        !          1678: { 246, "ouml", "latin small letter o with diaeresis, U+00F6 ISOlat1" },
        !          1679: { 247, "divide","division sign, U+00F7 ISOnum" },
        !          1680: { 248, "oslash","latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1" },
        !          1681: { 249, "ugrave","latin small letter u with grave, U+00F9 ISOlat1" },
        !          1682: { 250, "uacute","latin small letter u with acute, U+00FA ISOlat1" },
        !          1683: { 251, "ucirc","latin small letter u with circumflex, U+00FB ISOlat1" },
        !          1684: { 252, "uuml", "latin small letter u with diaeresis, U+00FC ISOlat1" },
        !          1685: { 253, "yacute","latin small letter y with acute, U+00FD ISOlat1" },
        !          1686: { 254, "thorn","latin small letter thorn with, U+00FE ISOlat1" },
        !          1687: { 255, "yuml", "latin small letter y with diaeresis, U+00FF ISOlat1" },
        !          1688: 
        !          1689: { 338, "OElig","latin capital ligature OE, U+0152 ISOlat2" },
        !          1690: { 339, "oelig","latin small ligature oe, U+0153 ISOlat2" },
        !          1691: { 352, "Scaron","latin capital letter S with caron, U+0160 ISOlat2" },
        !          1692: { 353, "scaron","latin small letter s with caron, U+0161 ISOlat2" },
        !          1693: { 376, "Yuml", "latin capital letter Y with diaeresis, U+0178 ISOlat2" },
        !          1694: 
        !          1695: /*
        !          1696:  * Anything below should really be kept as entities references
        !          1697:  */
        !          1698: { 402, "fnof", "latin small f with hook = function = florin, U+0192 ISOtech" },
        !          1699: 
        !          1700: { 710, "circ", "modifier letter circumflex accent, U+02C6 ISOpub" },
        !          1701: { 732, "tilde","small tilde, U+02DC ISOdia" },
        !          1702: 
        !          1703: { 913, "Alpha","greek capital letter alpha, U+0391" },
        !          1704: { 914, "Beta", "greek capital letter beta, U+0392" },
        !          1705: { 915, "Gamma","greek capital letter gamma, U+0393 ISOgrk3" },
        !          1706: { 916, "Delta","greek capital letter delta, U+0394 ISOgrk3" },
        !          1707: { 917, "Epsilon","greek capital letter epsilon, U+0395" },
        !          1708: { 918, "Zeta", "greek capital letter zeta, U+0396" },
        !          1709: { 919, "Eta",  "greek capital letter eta, U+0397" },
        !          1710: { 920, "Theta","greek capital letter theta, U+0398 ISOgrk3" },
        !          1711: { 921, "Iota", "greek capital letter iota, U+0399" },
        !          1712: { 922, "Kappa","greek capital letter kappa, U+039A" },
        !          1713: { 923, "Lambda", "greek capital letter lambda, U+039B ISOgrk3" },
        !          1714: { 924, "Mu",   "greek capital letter mu, U+039C" },
        !          1715: { 925, "Nu",   "greek capital letter nu, U+039D" },
        !          1716: { 926, "Xi",   "greek capital letter xi, U+039E ISOgrk3" },
        !          1717: { 927, "Omicron","greek capital letter omicron, U+039F" },
        !          1718: { 928, "Pi",   "greek capital letter pi, U+03A0 ISOgrk3" },
        !          1719: { 929, "Rho",  "greek capital letter rho, U+03A1" },
        !          1720: { 931, "Sigma","greek capital letter sigma, U+03A3 ISOgrk3" },
        !          1721: { 932, "Tau",  "greek capital letter tau, U+03A4" },
        !          1722: { 933, "Upsilon","greek capital letter upsilon, U+03A5 ISOgrk3" },
        !          1723: { 934, "Phi",  "greek capital letter phi, U+03A6 ISOgrk3" },
        !          1724: { 935, "Chi",  "greek capital letter chi, U+03A7" },
        !          1725: { 936, "Psi",  "greek capital letter psi, U+03A8 ISOgrk3" },
        !          1726: { 937, "Omega","greek capital letter omega, U+03A9 ISOgrk3" },
        !          1727: 
        !          1728: { 945, "alpha","greek small letter alpha, U+03B1 ISOgrk3" },
        !          1729: { 946, "beta", "greek small letter beta, U+03B2 ISOgrk3" },
        !          1730: { 947, "gamma","greek small letter gamma, U+03B3 ISOgrk3" },
        !          1731: { 948, "delta","greek small letter delta, U+03B4 ISOgrk3" },
        !          1732: { 949, "epsilon","greek small letter epsilon, U+03B5 ISOgrk3" },
        !          1733: { 950, "zeta", "greek small letter zeta, U+03B6 ISOgrk3" },
        !          1734: { 951, "eta",  "greek small letter eta, U+03B7 ISOgrk3" },
        !          1735: { 952, "theta","greek small letter theta, U+03B8 ISOgrk3" },
        !          1736: { 953, "iota", "greek small letter iota, U+03B9 ISOgrk3" },
        !          1737: { 954, "kappa","greek small letter kappa, U+03BA ISOgrk3" },
        !          1738: { 955, "lambda","greek small letter lambda, U+03BB ISOgrk3" },
        !          1739: { 956, "mu",   "greek small letter mu, U+03BC ISOgrk3" },
        !          1740: { 957, "nu",   "greek small letter nu, U+03BD ISOgrk3" },
        !          1741: { 958, "xi",   "greek small letter xi, U+03BE ISOgrk3" },
        !          1742: { 959, "omicron","greek small letter omicron, U+03BF NEW" },
        !          1743: { 960, "pi",   "greek small letter pi, U+03C0 ISOgrk3" },
        !          1744: { 961, "rho",  "greek small letter rho, U+03C1 ISOgrk3" },
        !          1745: { 962, "sigmaf","greek small letter final sigma, U+03C2 ISOgrk3" },
        !          1746: { 963, "sigma","greek small letter sigma, U+03C3 ISOgrk3" },
        !          1747: { 964, "tau",  "greek small letter tau, U+03C4 ISOgrk3" },
        !          1748: { 965, "upsilon","greek small letter upsilon, U+03C5 ISOgrk3" },
        !          1749: { 966, "phi",  "greek small letter phi, U+03C6 ISOgrk3" },
        !          1750: { 967, "chi",  "greek small letter chi, U+03C7 ISOgrk3" },
        !          1751: { 968, "psi",  "greek small letter psi, U+03C8 ISOgrk3" },
        !          1752: { 969, "omega","greek small letter omega, U+03C9 ISOgrk3" },
        !          1753: { 977, "thetasym","greek small letter theta symbol, U+03D1 NEW" },
        !          1754: { 978, "upsih","greek upsilon with hook symbol, U+03D2 NEW" },
        !          1755: { 982, "piv",  "greek pi symbol, U+03D6 ISOgrk3" },
        !          1756: 
        !          1757: { 8194,        "ensp", "en space, U+2002 ISOpub" },
        !          1758: { 8195,        "emsp", "em space, U+2003 ISOpub" },
        !          1759: { 8201,        "thinsp","thin space, U+2009 ISOpub" },
        !          1760: { 8204,        "zwnj", "zero width non-joiner, U+200C NEW RFC 2070" },
        !          1761: { 8205,        "zwj",  "zero width joiner, U+200D NEW RFC 2070" },
        !          1762: { 8206,        "lrm",  "left-to-right mark, U+200E NEW RFC 2070" },
        !          1763: { 8207,        "rlm",  "right-to-left mark, U+200F NEW RFC 2070" },
        !          1764: { 8211,        "ndash","en dash, U+2013 ISOpub" },
        !          1765: { 8212,        "mdash","em dash, U+2014 ISOpub" },
        !          1766: { 8216,        "lsquo","left single quotation mark, U+2018 ISOnum" },
        !          1767: { 8217,        "rsquo","right single quotation mark, U+2019 ISOnum" },
        !          1768: { 8218,        "sbquo","single low-9 quotation mark, U+201A NEW" },
        !          1769: { 8220,        "ldquo","left double quotation mark, U+201C ISOnum" },
        !          1770: { 8221,        "rdquo","right double quotation mark, U+201D ISOnum" },
        !          1771: { 8222,        "bdquo","double low-9 quotation mark, U+201E NEW" },
        !          1772: { 8224,        "dagger","dagger, U+2020 ISOpub" },
        !          1773: { 8225,        "Dagger","double dagger, U+2021 ISOpub" },
        !          1774: 
        !          1775: { 8226,        "bull", "bullet = black small circle, U+2022 ISOpub" },
        !          1776: { 8230,        "hellip","horizontal ellipsis = three dot leader, U+2026 ISOpub" },
        !          1777: 
        !          1778: { 8240,        "permil","per mille sign, U+2030 ISOtech" },
        !          1779: 
        !          1780: { 8242,        "prime","prime = minutes = feet, U+2032 ISOtech" },
        !          1781: { 8243,        "Prime","double prime = seconds = inches, U+2033 ISOtech" },
        !          1782: 
        !          1783: { 8249,        "lsaquo","single left-pointing angle quotation mark, U+2039 ISO proposed" },
        !          1784: { 8250,        "rsaquo","single right-pointing angle quotation mark, U+203A ISO proposed" },
        !          1785: 
        !          1786: { 8254,        "oline","overline = spacing overscore, U+203E NEW" },
        !          1787: { 8260,        "frasl","fraction slash, U+2044 NEW" },
        !          1788: 
        !          1789: { 8364,        "euro", "euro sign, U+20AC NEW" },
        !          1790: 
        !          1791: { 8465,        "image","blackletter capital I = imaginary part, U+2111 ISOamso" },
        !          1792: { 8472,        "weierp","script capital P = power set = Weierstrass p, U+2118 ISOamso" },
        !          1793: { 8476,        "real", "blackletter capital R = real part symbol, U+211C ISOamso" },
        !          1794: { 8482,        "trade","trade mark sign, U+2122 ISOnum" },
        !          1795: { 8501,        "alefsym","alef symbol = first transfinite cardinal, U+2135 NEW" },
        !          1796: { 8592,        "larr", "leftwards arrow, U+2190 ISOnum" },
        !          1797: { 8593,        "uarr", "upwards arrow, U+2191 ISOnum" },
        !          1798: { 8594,        "rarr", "rightwards arrow, U+2192 ISOnum" },
        !          1799: { 8595,        "darr", "downwards arrow, U+2193 ISOnum" },
        !          1800: { 8596,        "harr", "left right arrow, U+2194 ISOamsa" },
        !          1801: { 8629,        "crarr","downwards arrow with corner leftwards = carriage return, U+21B5 NEW" },
        !          1802: { 8656,        "lArr", "leftwards double arrow, U+21D0 ISOtech" },
        !          1803: { 8657,        "uArr", "upwards double arrow, U+21D1 ISOamsa" },
        !          1804: { 8658,        "rArr", "rightwards double arrow, U+21D2 ISOtech" },
        !          1805: { 8659,        "dArr", "downwards double arrow, U+21D3 ISOamsa" },
        !          1806: { 8660,        "hArr", "left right double arrow, U+21D4 ISOamsa" },
        !          1807: 
        !          1808: { 8704,        "forall","for all, U+2200 ISOtech" },
        !          1809: { 8706,        "part", "partial differential, U+2202 ISOtech" },
        !          1810: { 8707,        "exist","there exists, U+2203 ISOtech" },
        !          1811: { 8709,        "empty","empty set = null set = diameter, U+2205 ISOamso" },
        !          1812: { 8711,        "nabla","nabla = backward difference, U+2207 ISOtech" },
        !          1813: { 8712,        "isin", "element of, U+2208 ISOtech" },
        !          1814: { 8713,        "notin","not an element of, U+2209 ISOtech" },
        !          1815: { 8715,        "ni",   "contains as member, U+220B ISOtech" },
        !          1816: { 8719,        "prod", "n-ary product = product sign, U+220F ISOamsb" },
        !          1817: { 8721,        "sum",  "n-ary summation, U+2211 ISOamsb" },
        !          1818: { 8722,        "minus","minus sign, U+2212 ISOtech" },
        !          1819: { 8727,        "lowast","asterisk operator, U+2217 ISOtech" },
        !          1820: { 8730,        "radic","square root = radical sign, U+221A ISOtech" },
        !          1821: { 8733,        "prop", "proportional to, U+221D ISOtech" },
        !          1822: { 8734,        "infin","infinity, U+221E ISOtech" },
        !          1823: { 8736,        "ang",  "angle, U+2220 ISOamso" },
        !          1824: { 8743,        "and",  "logical and = wedge, U+2227 ISOtech" },
        !          1825: { 8744,        "or",   "logical or = vee, U+2228 ISOtech" },
        !          1826: { 8745,        "cap",  "intersection = cap, U+2229 ISOtech" },
        !          1827: { 8746,        "cup",  "union = cup, U+222A ISOtech" },
        !          1828: { 8747,        "int",  "integral, U+222B ISOtech" },
        !          1829: { 8756,        "there4","therefore, U+2234 ISOtech" },
        !          1830: { 8764,        "sim",  "tilde operator = varies with = similar to, U+223C ISOtech" },
        !          1831: { 8773,        "cong", "approximately equal to, U+2245 ISOtech" },
        !          1832: { 8776,        "asymp","almost equal to = asymptotic to, U+2248 ISOamsr" },
        !          1833: { 8800,        "ne",   "not equal to, U+2260 ISOtech" },
        !          1834: { 8801,        "equiv","identical to, U+2261 ISOtech" },
        !          1835: { 8804,        "le",   "less-than or equal to, U+2264 ISOtech" },
        !          1836: { 8805,        "ge",   "greater-than or equal to, U+2265 ISOtech" },
        !          1837: { 8834,        "sub",  "subset of, U+2282 ISOtech" },
        !          1838: { 8835,        "sup",  "superset of, U+2283 ISOtech" },
        !          1839: { 8836,        "nsub", "not a subset of, U+2284 ISOamsn" },
        !          1840: { 8838,        "sube", "subset of or equal to, U+2286 ISOtech" },
        !          1841: { 8839,        "supe", "superset of or equal to, U+2287 ISOtech" },
        !          1842: { 8853,        "oplus","circled plus = direct sum, U+2295 ISOamsb" },
        !          1843: { 8855,        "otimes","circled times = vector product, U+2297 ISOamsb" },
        !          1844: { 8869,        "perp", "up tack = orthogonal to = perpendicular, U+22A5 ISOtech" },
        !          1845: { 8901,        "sdot", "dot operator, U+22C5 ISOamsb" },
        !          1846: { 8968,        "lceil","left ceiling = apl upstile, U+2308 ISOamsc" },
        !          1847: { 8969,        "rceil","right ceiling, U+2309 ISOamsc" },
        !          1848: { 8970,        "lfloor","left floor = apl downstile, U+230A ISOamsc" },
        !          1849: { 8971,        "rfloor","right floor, U+230B ISOamsc" },
        !          1850: { 9001,        "lang", "left-pointing angle bracket = bra, U+2329 ISOtech" },
        !          1851: { 9002,        "rang", "right-pointing angle bracket = ket, U+232A ISOtech" },
        !          1852: { 9674,        "loz",  "lozenge, U+25CA ISOpub" },
        !          1853: 
        !          1854: { 9824,        "spades","black spade suit, U+2660 ISOpub" },
        !          1855: { 9827,        "clubs","black club suit = shamrock, U+2663 ISOpub" },
        !          1856: { 9829,        "hearts","black heart suit = valentine, U+2665 ISOpub" },
        !          1857: { 9830,        "diams","black diamond suit, U+2666 ISOpub" },
        !          1858: 
        !          1859: };
        !          1860: 
        !          1861: /************************************************************************
        !          1862:  *                                                                     *
        !          1863:  *             Commodity functions to handle entities                  *
        !          1864:  *                                                                     *
        !          1865:  ************************************************************************/
        !          1866: 
        !          1867: /*
        !          1868:  * Macro used to grow the current buffer.
        !          1869:  */
        !          1870: #define growBuffer(buffer) {                                           \
        !          1871:     xmlChar *tmp;                                                      \
        !          1872:     buffer##_size *= 2;                                                        \
        !          1873:     tmp = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
        !          1874:     if (tmp == NULL) {                                         \
        !          1875:        htmlErrMemory(ctxt, "growing buffer\n");                        \
        !          1876:        xmlFree(buffer);                                                \
        !          1877:        return(NULL);                                                   \
        !          1878:     }                                                                  \
        !          1879:     buffer = tmp;                                                      \
        !          1880: }
        !          1881: 
        !          1882: /**
        !          1883:  * htmlEntityLookup:
        !          1884:  * @name: the entity name
        !          1885:  *
        !          1886:  * Lookup the given entity in EntitiesTable
        !          1887:  *
        !          1888:  * TODO: the linear scan is really ugly, an hash table is really needed.
        !          1889:  *
        !          1890:  * Returns the associated htmlEntityDescPtr if found, NULL otherwise.
        !          1891:  */
        !          1892: const htmlEntityDesc *
        !          1893: htmlEntityLookup(const xmlChar *name) {
        !          1894:     unsigned int i;
        !          1895: 
        !          1896:     for (i = 0;i < (sizeof(html40EntitiesTable)/
        !          1897:                     sizeof(html40EntitiesTable[0]));i++) {
        !          1898:         if (xmlStrEqual(name, BAD_CAST html40EntitiesTable[i].name)) {
        !          1899:             return((htmlEntityDescPtr) &html40EntitiesTable[i]);
        !          1900:        }
        !          1901:     }
        !          1902:     return(NULL);
        !          1903: }
        !          1904: 
        !          1905: /**
        !          1906:  * htmlEntityValueLookup:
        !          1907:  * @value: the entity's unicode value
        !          1908:  *
        !          1909:  * Lookup the given entity in EntitiesTable
        !          1910:  *
        !          1911:  * TODO: the linear scan is really ugly, an hash table is really needed.
        !          1912:  *
        !          1913:  * Returns the associated htmlEntityDescPtr if found, NULL otherwise.
        !          1914:  */
        !          1915: const htmlEntityDesc *
        !          1916: htmlEntityValueLookup(unsigned int value) {
        !          1917:     unsigned int i;
        !          1918: 
        !          1919:     for (i = 0;i < (sizeof(html40EntitiesTable)/
        !          1920:                     sizeof(html40EntitiesTable[0]));i++) {
        !          1921:         if (html40EntitiesTable[i].value >= value) {
        !          1922:            if (html40EntitiesTable[i].value > value)
        !          1923:                break;
        !          1924:             return((htmlEntityDescPtr) &html40EntitiesTable[i]);
        !          1925:        }
        !          1926:     }
        !          1927:     return(NULL);
        !          1928: }
        !          1929: 
        !          1930: /**
        !          1931:  * UTF8ToHtml:
        !          1932:  * @out:  a pointer to an array of bytes to store the result
        !          1933:  * @outlen:  the length of @out
        !          1934:  * @in:  a pointer to an array of UTF-8 chars
        !          1935:  * @inlen:  the length of @in
        !          1936:  *
        !          1937:  * Take a block of UTF-8 chars in and try to convert it to an ASCII
        !          1938:  * plus HTML entities block of chars out.
        !          1939:  *
        !          1940:  * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
        !          1941:  * The value of @inlen after return is the number of octets consumed
        !          1942:  *     as the return value is positive, else unpredictable.
        !          1943:  * The value of @outlen after return is the number of octets consumed.
        !          1944:  */
        !          1945: int
        !          1946: UTF8ToHtml(unsigned char* out, int *outlen,
        !          1947:               const unsigned char* in, int *inlen) {
        !          1948:     const unsigned char* processed = in;
        !          1949:     const unsigned char* outend;
        !          1950:     const unsigned char* outstart = out;
        !          1951:     const unsigned char* instart = in;
        !          1952:     const unsigned char* inend;
        !          1953:     unsigned int c, d;
        !          1954:     int trailing;
        !          1955: 
        !          1956:     if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
        !          1957:     if (in == NULL) {
        !          1958:         /*
        !          1959:         * initialization nothing to do
        !          1960:         */
        !          1961:        *outlen = 0;
        !          1962:        *inlen = 0;
        !          1963:        return(0);
        !          1964:     }
        !          1965:     inend = in + (*inlen);
        !          1966:     outend = out + (*outlen);
        !          1967:     while (in < inend) {
        !          1968:        d = *in++;
        !          1969:        if      (d < 0x80)  { c= d; trailing= 0; }
        !          1970:        else if (d < 0xC0) {
        !          1971:            /* trailing byte in leading position */
        !          1972:            *outlen = out - outstart;
        !          1973:            *inlen = processed - instart;
        !          1974:            return(-2);
        !          1975:         } else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
        !          1976:         else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
        !          1977:         else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
        !          1978:        else {
        !          1979:            /* no chance for this in Ascii */
        !          1980:            *outlen = out - outstart;
        !          1981:            *inlen = processed - instart;
        !          1982:            return(-2);
        !          1983:        }
        !          1984: 
        !          1985:        if (inend - in < trailing) {
        !          1986:            break;
        !          1987:        }
        !          1988: 
        !          1989:        for ( ; trailing; trailing--) {
        !          1990:            if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80))
        !          1991:                break;
        !          1992:            c <<= 6;
        !          1993:            c |= d & 0x3F;
        !          1994:        }
        !          1995: 
        !          1996:        /* assertion: c is a single UTF-4 value */
        !          1997:        if (c < 0x80) {
        !          1998:            if (out + 1 >= outend)
        !          1999:                break;
        !          2000:            *out++ = c;
        !          2001:        } else {
        !          2002:            int len;
        !          2003:            const htmlEntityDesc * ent;
        !          2004:            const char *cp;
        !          2005:            char nbuf[16];
        !          2006: 
        !          2007:            /*
        !          2008:             * Try to lookup a predefined HTML entity for it
        !          2009:             */
        !          2010: 
        !          2011:            ent = htmlEntityValueLookup(c);
        !          2012:            if (ent == NULL) {
        !          2013:              snprintf(nbuf, sizeof(nbuf), "#%u", c);
        !          2014:              cp = nbuf;
        !          2015:            }
        !          2016:            else
        !          2017:              cp = ent->name;
        !          2018:            len = strlen(cp);
        !          2019:            if (out + 2 + len >= outend)
        !          2020:                break;
        !          2021:            *out++ = '&';
        !          2022:            memcpy(out, cp, len);
        !          2023:            out += len;
        !          2024:            *out++ = ';';
        !          2025:        }
        !          2026:        processed = in;
        !          2027:     }
        !          2028:     *outlen = out - outstart;
        !          2029:     *inlen = processed - instart;
        !          2030:     return(0);
        !          2031: }
        !          2032: 
        !          2033: /**
        !          2034:  * htmlEncodeEntities:
        !          2035:  * @out:  a pointer to an array of bytes to store the result
        !          2036:  * @outlen:  the length of @out
        !          2037:  * @in:  a pointer to an array of UTF-8 chars
        !          2038:  * @inlen:  the length of @in
        !          2039:  * @quoteChar: the quote character to escape (' or ") or zero.
        !          2040:  *
        !          2041:  * Take a block of UTF-8 chars in and try to convert it to an ASCII
        !          2042:  * plus HTML entities block of chars out.
        !          2043:  *
        !          2044:  * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
        !          2045:  * The value of @inlen after return is the number of octets consumed
        !          2046:  *     as the return value is positive, else unpredictable.
        !          2047:  * The value of @outlen after return is the number of octets consumed.
        !          2048:  */
        !          2049: int
        !          2050: htmlEncodeEntities(unsigned char* out, int *outlen,
        !          2051:                   const unsigned char* in, int *inlen, int quoteChar) {
        !          2052:     const unsigned char* processed = in;
        !          2053:     const unsigned char* outend;
        !          2054:     const unsigned char* outstart = out;
        !          2055:     const unsigned char* instart = in;
        !          2056:     const unsigned char* inend;
        !          2057:     unsigned int c, d;
        !          2058:     int trailing;
        !          2059: 
        !          2060:     if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL))
        !          2061:         return(-1);
        !          2062:     outend = out + (*outlen);
        !          2063:     inend = in + (*inlen);
        !          2064:     while (in < inend) {
        !          2065:        d = *in++;
        !          2066:        if      (d < 0x80)  { c= d; trailing= 0; }
        !          2067:        else if (d < 0xC0) {
        !          2068:            /* trailing byte in leading position */
        !          2069:            *outlen = out - outstart;
        !          2070:            *inlen = processed - instart;
        !          2071:            return(-2);
        !          2072:         } else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
        !          2073:         else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
        !          2074:         else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
        !          2075:        else {
        !          2076:            /* no chance for this in Ascii */
        !          2077:            *outlen = out - outstart;
        !          2078:            *inlen = processed - instart;
        !          2079:            return(-2);
        !          2080:        }
        !          2081: 
        !          2082:        if (inend - in < trailing)
        !          2083:            break;
        !          2084: 
        !          2085:        while (trailing--) {
        !          2086:            if (((d= *in++) & 0xC0) != 0x80) {
        !          2087:                *outlen = out - outstart;
        !          2088:                *inlen = processed - instart;
        !          2089:                return(-2);
        !          2090:            }
        !          2091:            c <<= 6;
        !          2092:            c |= d & 0x3F;
        !          2093:        }
        !          2094: 
        !          2095:        /* assertion: c is a single UTF-4 value */
        !          2096:        if ((c < 0x80) && (c != (unsigned int) quoteChar) &&
        !          2097:            (c != '&') && (c != '<') && (c != '>')) {
        !          2098:            if (out >= outend)
        !          2099:                break;
        !          2100:            *out++ = c;
        !          2101:        } else {
        !          2102:            const htmlEntityDesc * ent;
        !          2103:            const char *cp;
        !          2104:            char nbuf[16];
        !          2105:            int len;
        !          2106: 
        !          2107:            /*
        !          2108:             * Try to lookup a predefined HTML entity for it
        !          2109:             */
        !          2110:            ent = htmlEntityValueLookup(c);
        !          2111:            if (ent == NULL) {
        !          2112:                snprintf(nbuf, sizeof(nbuf), "#%u", c);
        !          2113:                cp = nbuf;
        !          2114:            }
        !          2115:            else
        !          2116:                cp = ent->name;
        !          2117:            len = strlen(cp);
        !          2118:            if (out + 2 + len > outend)
        !          2119:                break;
        !          2120:            *out++ = '&';
        !          2121:            memcpy(out, cp, len);
        !          2122:            out += len;
        !          2123:            *out++ = ';';
        !          2124:        }
        !          2125:        processed = in;
        !          2126:     }
        !          2127:     *outlen = out - outstart;
        !          2128:     *inlen = processed - instart;
        !          2129:     return(0);
        !          2130: }
        !          2131: 
        !          2132: /************************************************************************
        !          2133:  *                                                                     *
        !          2134:  *             Commodity functions to handle streams                   *
        !          2135:  *                                                                     *
        !          2136:  ************************************************************************/
        !          2137: 
        !          2138: /**
        !          2139:  * htmlNewInputStream:
        !          2140:  * @ctxt:  an HTML parser context
        !          2141:  *
        !          2142:  * Create a new input stream structure
        !          2143:  * Returns the new input stream or NULL
        !          2144:  */
        !          2145: static htmlParserInputPtr
        !          2146: htmlNewInputStream(htmlParserCtxtPtr ctxt) {
        !          2147:     htmlParserInputPtr input;
        !          2148: 
        !          2149:     input = (xmlParserInputPtr) xmlMalloc(sizeof(htmlParserInput));
        !          2150:     if (input == NULL) {
        !          2151:         htmlErrMemory(ctxt, "couldn't allocate a new input stream\n");
        !          2152:        return(NULL);
        !          2153:     }
        !          2154:     memset(input, 0, sizeof(htmlParserInput));
        !          2155:     input->filename = NULL;
        !          2156:     input->directory = NULL;
        !          2157:     input->base = NULL;
        !          2158:     input->cur = NULL;
        !          2159:     input->buf = NULL;
        !          2160:     input->line = 1;
        !          2161:     input->col = 1;
        !          2162:     input->buf = NULL;
        !          2163:     input->free = NULL;
        !          2164:     input->version = NULL;
        !          2165:     input->consumed = 0;
        !          2166:     input->length = 0;
        !          2167:     return(input);
        !          2168: }
        !          2169: 
        !          2170: 
        !          2171: /************************************************************************
        !          2172:  *                                                                     *
        !          2173:  *             Commodity functions, cleanup needed ?                   *
        !          2174:  *                                                                     *
        !          2175:  ************************************************************************/
        !          2176: /*
        !          2177:  * all tags allowing pc data from the html 4.01 loose dtd
        !          2178:  * NOTE: it might be more apropriate to integrate this information
        !          2179:  * into the html40ElementTable array but I don't want to risk any
        !          2180:  * binary incomptibility
        !          2181:  */
        !          2182: static const char *allowPCData[] = {
        !          2183:     "a", "abbr", "acronym", "address", "applet", "b", "bdo", "big",
        !          2184:     "blockquote", "body", "button", "caption", "center", "cite", "code",
        !          2185:     "dd", "del", "dfn", "div", "dt", "em", "font", "form", "h1", "h2",
        !          2186:     "h3", "h4", "h5", "h6", "i", "iframe", "ins", "kbd", "label", "legend",
        !          2187:     "li", "noframes", "noscript", "object", "p", "pre", "q", "s", "samp",
        !          2188:     "small", "span", "strike", "strong", "td", "th", "tt", "u", "var"
        !          2189: };
        !          2190: 
        !          2191: /**
        !          2192:  * areBlanks:
        !          2193:  * @ctxt:  an HTML parser context
        !          2194:  * @str:  a xmlChar *
        !          2195:  * @len:  the size of @str
        !          2196:  *
        !          2197:  * Is this a sequence of blank chars that one can ignore ?
        !          2198:  *
        !          2199:  * Returns 1 if ignorable 0 otherwise.
        !          2200:  */
        !          2201: 
        !          2202: static int areBlanks(htmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
        !          2203:     unsigned int i;
        !          2204:     int j;
        !          2205:     xmlNodePtr lastChild;
        !          2206:     xmlDtdPtr dtd;
        !          2207: 
        !          2208:     for (j = 0;j < len;j++)
        !          2209:         if (!(IS_BLANK_CH(str[j]))) return(0);
        !          2210: 
        !          2211:     if (CUR == 0) return(1);
        !          2212:     if (CUR != '<') return(0);
        !          2213:     if (ctxt->name == NULL)
        !          2214:        return(1);
        !          2215:     if (xmlStrEqual(ctxt->name, BAD_CAST"html"))
        !          2216:        return(1);
        !          2217:     if (xmlStrEqual(ctxt->name, BAD_CAST"head"))
        !          2218:        return(1);
        !          2219: 
        !          2220:     /* Only strip CDATA children of the body tag for strict HTML DTDs */
        !          2221:     if (xmlStrEqual(ctxt->name, BAD_CAST "body") && ctxt->myDoc != NULL) {
        !          2222:         dtd = xmlGetIntSubset(ctxt->myDoc);
        !          2223:         if (dtd != NULL && dtd->ExternalID != NULL) {
        !          2224:             if (!xmlStrcasecmp(dtd->ExternalID, BAD_CAST "-//W3C//DTD HTML 4.01//EN") ||
        !          2225:                     !xmlStrcasecmp(dtd->ExternalID, BAD_CAST "-//W3C//DTD HTML 4//EN"))
        !          2226:                 return(1);
        !          2227:         }
        !          2228:     }
        !          2229: 
        !          2230:     if (ctxt->node == NULL) return(0);
        !          2231:     lastChild = xmlGetLastChild(ctxt->node);
        !          2232:     while ((lastChild) && (lastChild->type == XML_COMMENT_NODE))
        !          2233:        lastChild = lastChild->prev;
        !          2234:     if (lastChild == NULL) {
        !          2235:         if ((ctxt->node->type != XML_ELEMENT_NODE) &&
        !          2236:             (ctxt->node->content != NULL)) return(0);
        !          2237:        /* keep ws in constructs like ...<b> </b>...
        !          2238:           for all tags "b" allowing PCDATA */
        !          2239:        for ( i = 0; i < sizeof(allowPCData)/sizeof(allowPCData[0]); i++ ) {
        !          2240:            if ( xmlStrEqual(ctxt->name, BAD_CAST allowPCData[i]) ) {
        !          2241:                return(0);
        !          2242:            }
        !          2243:        }
        !          2244:     } else if (xmlNodeIsText(lastChild)) {
        !          2245:         return(0);
        !          2246:     } else {
        !          2247:        /* keep ws in constructs like <p><b>xy</b> <i>z</i><p>
        !          2248:           for all tags "p" allowing PCDATA */
        !          2249:        for ( i = 0; i < sizeof(allowPCData)/sizeof(allowPCData[0]); i++ ) {
        !          2250:            if ( xmlStrEqual(lastChild->name, BAD_CAST allowPCData[i]) ) {
        !          2251:                return(0);
        !          2252:            }
        !          2253:        }
        !          2254:     }
        !          2255:     return(1);
        !          2256: }
        !          2257: 
        !          2258: /**
        !          2259:  * htmlNewDocNoDtD:
        !          2260:  * @URI:  URI for the dtd, or NULL
        !          2261:  * @ExternalID:  the external ID of the DTD, or NULL
        !          2262:  *
        !          2263:  * Creates a new HTML document without a DTD node if @URI and @ExternalID
        !          2264:  * are NULL
        !          2265:  *
        !          2266:  * Returns a new document, do not initialize the DTD if not provided
        !          2267:  */
        !          2268: htmlDocPtr
        !          2269: htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) {
        !          2270:     xmlDocPtr cur;
        !          2271: 
        !          2272:     /*
        !          2273:      * Allocate a new document and fill the fields.
        !          2274:      */
        !          2275:     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
        !          2276:     if (cur == NULL) {
        !          2277:        htmlErrMemory(NULL, "HTML document creation failed\n");
        !          2278:        return(NULL);
        !          2279:     }
        !          2280:     memset(cur, 0, sizeof(xmlDoc));
        !          2281: 
        !          2282:     cur->type = XML_HTML_DOCUMENT_NODE;
        !          2283:     cur->version = NULL;
        !          2284:     cur->intSubset = NULL;
        !          2285:     cur->doc = cur;
        !          2286:     cur->name = NULL;
        !          2287:     cur->children = NULL;
        !          2288:     cur->extSubset = NULL;
        !          2289:     cur->oldNs = NULL;
        !          2290:     cur->encoding = NULL;
        !          2291:     cur->standalone = 1;
        !          2292:     cur->compression = 0;
        !          2293:     cur->ids = NULL;
        !          2294:     cur->refs = NULL;
        !          2295:     cur->_private = NULL;
        !          2296:     cur->charset = XML_CHAR_ENCODING_UTF8;
        !          2297:     cur->properties = XML_DOC_HTML | XML_DOC_USERBUILT;
        !          2298:     if ((ExternalID != NULL) ||
        !          2299:        (URI != NULL))
        !          2300:        xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI);
        !          2301:     return(cur);
        !          2302: }
        !          2303: 
        !          2304: /**
        !          2305:  * htmlNewDoc:
        !          2306:  * @URI:  URI for the dtd, or NULL
        !          2307:  * @ExternalID:  the external ID of the DTD, or NULL
        !          2308:  *
        !          2309:  * Creates a new HTML document
        !          2310:  *
        !          2311:  * Returns a new document
        !          2312:  */
        !          2313: htmlDocPtr
        !          2314: htmlNewDoc(const xmlChar *URI, const xmlChar *ExternalID) {
        !          2315:     if ((URI == NULL) && (ExternalID == NULL))
        !          2316:        return(htmlNewDocNoDtD(
        !          2317:                    BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd",
        !          2318:                    BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN"));
        !          2319: 
        !          2320:     return(htmlNewDocNoDtD(URI, ExternalID));
        !          2321: }
        !          2322: 
        !          2323: 
        !          2324: /************************************************************************
        !          2325:  *                                                                     *
        !          2326:  *                     The parser itself                               *
        !          2327:  *     Relates to http://www.w3.org/TR/html40                          *
        !          2328:  *                                                                     *
        !          2329:  ************************************************************************/
        !          2330: 
        !          2331: /************************************************************************
        !          2332:  *                                                                     *
        !          2333:  *                     The parser itself                               *
        !          2334:  *                                                                     *
        !          2335:  ************************************************************************/
        !          2336: 
        !          2337: static const xmlChar * htmlParseNameComplex(xmlParserCtxtPtr ctxt);
        !          2338: 
        !          2339: /**
        !          2340:  * htmlParseHTMLName:
        !          2341:  * @ctxt:  an HTML parser context
        !          2342:  *
        !          2343:  * parse an HTML tag or attribute name, note that we convert it to lowercase
        !          2344:  * since HTML names are not case-sensitive.
        !          2345:  *
        !          2346:  * Returns the Tag Name parsed or NULL
        !          2347:  */
        !          2348: 
        !          2349: static const xmlChar *
        !          2350: htmlParseHTMLName(htmlParserCtxtPtr ctxt) {
        !          2351:     int i = 0;
        !          2352:     xmlChar loc[HTML_PARSER_BUFFER_SIZE];
        !          2353: 
        !          2354:     if (!IS_ASCII_LETTER(CUR) && (CUR != '_') &&
        !          2355:         (CUR != ':') && (CUR != '.')) return(NULL);
        !          2356: 
        !          2357:     while ((i < HTML_PARSER_BUFFER_SIZE) &&
        !          2358:            ((IS_ASCII_LETTER(CUR)) || (IS_ASCII_DIGIT(CUR)) ||
        !          2359:           (CUR == ':') || (CUR == '-') || (CUR == '_') ||
        !          2360:            (CUR == '.'))) {
        !          2361:        if ((CUR >= 'A') && (CUR <= 'Z')) loc[i] = CUR + 0x20;
        !          2362:         else loc[i] = CUR;
        !          2363:        i++;
        !          2364: 
        !          2365:        NEXT;
        !          2366:     }
        !          2367: 
        !          2368:     return(xmlDictLookup(ctxt->dict, loc, i));
        !          2369: }
        !          2370: 
        !          2371: 
        !          2372: /**
        !          2373:  * htmlParseHTMLName_nonInvasive:
        !          2374:  * @ctxt:  an HTML parser context
        !          2375:  *
        !          2376:  * parse an HTML tag or attribute name, note that we convert it to lowercase
        !          2377:  * since HTML names are not case-sensitive, this doesn't consume the data
        !          2378:  * from the stream, it's a look-ahead
        !          2379:  *
        !          2380:  * Returns the Tag Name parsed or NULL
        !          2381:  */
        !          2382: 
        !          2383: static const xmlChar *
        !          2384: htmlParseHTMLName_nonInvasive(htmlParserCtxtPtr ctxt) {
        !          2385:     int i = 0;
        !          2386:     xmlChar loc[HTML_PARSER_BUFFER_SIZE];
        !          2387: 
        !          2388:     if (!IS_ASCII_LETTER(NXT(1)) && (NXT(1) != '_') &&
        !          2389:         (NXT(1) != ':')) return(NULL);
        !          2390: 
        !          2391:     while ((i < HTML_PARSER_BUFFER_SIZE) &&
        !          2392:            ((IS_ASCII_LETTER(NXT(1+i))) || (IS_ASCII_DIGIT(NXT(1+i))) ||
        !          2393:           (NXT(1+i) == ':') || (NXT(1+i) == '-') || (NXT(1+i) == '_'))) {
        !          2394:        if ((NXT(1+i) >= 'A') && (NXT(1+i) <= 'Z')) loc[i] = NXT(1+i) + 0x20;
        !          2395:         else loc[i] = NXT(1+i);
        !          2396:        i++;
        !          2397:     }
        !          2398: 
        !          2399:     return(xmlDictLookup(ctxt->dict, loc, i));
        !          2400: }
        !          2401: 
        !          2402: 
        !          2403: /**
        !          2404:  * htmlParseName:
        !          2405:  * @ctxt:  an HTML parser context
        !          2406:  *
        !          2407:  * parse an HTML name, this routine is case sensitive.
        !          2408:  *
        !          2409:  * Returns the Name parsed or NULL
        !          2410:  */
        !          2411: 
        !          2412: static const xmlChar *
        !          2413: htmlParseName(htmlParserCtxtPtr ctxt) {
        !          2414:     const xmlChar *in;
        !          2415:     const xmlChar *ret;
        !          2416:     int count = 0;
        !          2417: 
        !          2418:     GROW;
        !          2419: 
        !          2420:     /*
        !          2421:      * Accelerator for simple ASCII names
        !          2422:      */
        !          2423:     in = ctxt->input->cur;
        !          2424:     if (((*in >= 0x61) && (*in <= 0x7A)) ||
        !          2425:        ((*in >= 0x41) && (*in <= 0x5A)) ||
        !          2426:        (*in == '_') || (*in == ':')) {
        !          2427:        in++;
        !          2428:        while (((*in >= 0x61) && (*in <= 0x7A)) ||
        !          2429:               ((*in >= 0x41) && (*in <= 0x5A)) ||
        !          2430:               ((*in >= 0x30) && (*in <= 0x39)) ||
        !          2431:               (*in == '_') || (*in == '-') ||
        !          2432:               (*in == ':') || (*in == '.'))
        !          2433:            in++;
        !          2434:        if ((*in > 0) && (*in < 0x80)) {
        !          2435:            count = in - ctxt->input->cur;
        !          2436:            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
        !          2437:            ctxt->input->cur = in;
        !          2438:            ctxt->nbChars += count;
        !          2439:            ctxt->input->col += count;
        !          2440:            return(ret);
        !          2441:        }
        !          2442:     }
        !          2443:     return(htmlParseNameComplex(ctxt));
        !          2444: }
        !          2445: 
        !          2446: static const xmlChar *
        !          2447: htmlParseNameComplex(xmlParserCtxtPtr ctxt) {
        !          2448:     int len = 0, l;
        !          2449:     int c;
        !          2450:     int count = 0;
        !          2451: 
        !          2452:     /*
        !          2453:      * Handler for more complex cases
        !          2454:      */
        !          2455:     GROW;
        !          2456:     c = CUR_CHAR(l);
        !          2457:     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
        !          2458:        (!IS_LETTER(c) && (c != '_') &&
        !          2459:          (c != ':'))) {
        !          2460:        return(NULL);
        !          2461:     }
        !          2462: 
        !          2463:     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
        !          2464:           ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
        !          2465:             (c == '.') || (c == '-') ||
        !          2466:            (c == '_') || (c == ':') ||
        !          2467:            (IS_COMBINING(c)) ||
        !          2468:            (IS_EXTENDER(c)))) {
        !          2469:        if (count++ > 100) {
        !          2470:            count = 0;
        !          2471:            GROW;
        !          2472:        }
        !          2473:        len += l;
        !          2474:        NEXTL(l);
        !          2475:        c = CUR_CHAR(l);
        !          2476:     }
        !          2477:     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
        !          2478: }
        !          2479: 
        !          2480: 
        !          2481: /**
        !          2482:  * htmlParseHTMLAttribute:
        !          2483:  * @ctxt:  an HTML parser context
        !          2484:  * @stop:  a char stop value
        !          2485:  *
        !          2486:  * parse an HTML attribute value till the stop (quote), if
        !          2487:  * stop is 0 then it stops at the first space
        !          2488:  *
        !          2489:  * Returns the attribute parsed or NULL
        !          2490:  */
        !          2491: 
        !          2492: static xmlChar *
        !          2493: htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) {
        !          2494:     xmlChar *buffer = NULL;
        !          2495:     int buffer_size = 0;
        !          2496:     xmlChar *out = NULL;
        !          2497:     const xmlChar *name = NULL;
        !          2498:     const xmlChar *cur = NULL;
        !          2499:     const htmlEntityDesc * ent;
        !          2500: 
        !          2501:     /*
        !          2502:      * allocate a translation buffer.
        !          2503:      */
        !          2504:     buffer_size = HTML_PARSER_BUFFER_SIZE;
        !          2505:     buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
        !          2506:     if (buffer == NULL) {
        !          2507:        htmlErrMemory(ctxt, "buffer allocation failed\n");
        !          2508:        return(NULL);
        !          2509:     }
        !          2510:     out = buffer;
        !          2511: 
        !          2512:     /*
        !          2513:      * Ok loop until we reach one of the ending chars
        !          2514:      */
        !          2515:     while ((CUR != 0) && (CUR != stop)) {
        !          2516:        if ((stop == 0) && (CUR == '>')) break;
        !          2517:        if ((stop == 0) && (IS_BLANK_CH(CUR))) break;
        !          2518:         if (CUR == '&') {
        !          2519:            if (NXT(1) == '#') {
        !          2520:                unsigned int c;
        !          2521:                int bits;
        !          2522: 
        !          2523:                c = htmlParseCharRef(ctxt);
        !          2524:                if      (c <    0x80)
        !          2525:                        { *out++  = c;                bits= -6; }
        !          2526:                else if (c <   0x800)
        !          2527:                        { *out++  =((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
        !          2528:                else if (c < 0x10000)
        !          2529:                        { *out++  =((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
        !          2530:                else
        !          2531:                        { *out++  =((c >> 18) & 0x07) | 0xF0;  bits= 12; }
        !          2532: 
        !          2533:                for ( ; bits >= 0; bits-= 6) {
        !          2534:                    *out++  = ((c >> bits) & 0x3F) | 0x80;
        !          2535:                }
        !          2536: 
        !          2537:                if (out - buffer > buffer_size - 100) {
        !          2538:                        int indx = out - buffer;
        !          2539: 
        !          2540:                        growBuffer(buffer);
        !          2541:                        out = &buffer[indx];
        !          2542:                }
        !          2543:            } else {
        !          2544:                ent = htmlParseEntityRef(ctxt, &name);
        !          2545:                if (name == NULL) {
        !          2546:                    *out++ = '&';
        !          2547:                    if (out - buffer > buffer_size - 100) {
        !          2548:                        int indx = out - buffer;
        !          2549: 
        !          2550:                        growBuffer(buffer);
        !          2551:                        out = &buffer[indx];
        !          2552:                    }
        !          2553:                } else if (ent == NULL) {
        !          2554:                    *out++ = '&';
        !          2555:                    cur = name;
        !          2556:                    while (*cur != 0) {
        !          2557:                        if (out - buffer > buffer_size - 100) {
        !          2558:                            int indx = out - buffer;
        !          2559: 
        !          2560:                            growBuffer(buffer);
        !          2561:                            out = &buffer[indx];
        !          2562:                        }
        !          2563:                        *out++ = *cur++;
        !          2564:                    }
        !          2565:                } else {
        !          2566:                    unsigned int c;
        !          2567:                    int bits;
        !          2568: 
        !          2569:                    if (out - buffer > buffer_size - 100) {
        !          2570:                        int indx = out - buffer;
        !          2571: 
        !          2572:                        growBuffer(buffer);
        !          2573:                        out = &buffer[indx];
        !          2574:                    }
        !          2575:                    c = ent->value;
        !          2576:                    if      (c <    0x80)
        !          2577:                        { *out++  = c;                bits= -6; }
        !          2578:                    else if (c <   0x800)
        !          2579:                        { *out++  =((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
        !          2580:                    else if (c < 0x10000)
        !          2581:                        { *out++  =((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
        !          2582:                    else
        !          2583:                        { *out++  =((c >> 18) & 0x07) | 0xF0;  bits= 12; }
        !          2584: 
        !          2585:                    for ( ; bits >= 0; bits-= 6) {
        !          2586:                        *out++  = ((c >> bits) & 0x3F) | 0x80;
        !          2587:                    }
        !          2588:                }
        !          2589:            }
        !          2590:        } else {
        !          2591:            unsigned int c;
        !          2592:            int bits, l;
        !          2593: 
        !          2594:            if (out - buffer > buffer_size - 100) {
        !          2595:                int indx = out - buffer;
        !          2596: 
        !          2597:                growBuffer(buffer);
        !          2598:                out = &buffer[indx];
        !          2599:            }
        !          2600:            c = CUR_CHAR(l);
        !          2601:            if      (c <    0x80)
        !          2602:                    { *out++  = c;                bits= -6; }
        !          2603:            else if (c <   0x800)
        !          2604:                    { *out++  =((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
        !          2605:            else if (c < 0x10000)
        !          2606:                    { *out++  =((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
        !          2607:            else
        !          2608:                    { *out++  =((c >> 18) & 0x07) | 0xF0;  bits= 12; }
        !          2609: 
        !          2610:            for ( ; bits >= 0; bits-= 6) {
        !          2611:                *out++  = ((c >> bits) & 0x3F) | 0x80;
        !          2612:            }
        !          2613:            NEXT;
        !          2614:        }
        !          2615:     }
        !          2616:     *out = 0;
        !          2617:     return(buffer);
        !          2618: }
        !          2619: 
        !          2620: /**
        !          2621:  * htmlParseEntityRef:
        !          2622:  * @ctxt:  an HTML parser context
        !          2623:  * @str:  location to store the entity name
        !          2624:  *
        !          2625:  * parse an HTML ENTITY references
        !          2626:  *
        !          2627:  * [68] EntityRef ::= '&' Name ';'
        !          2628:  *
        !          2629:  * Returns the associated htmlEntityDescPtr if found, or NULL otherwise,
        !          2630:  *         if non-NULL *str will have to be freed by the caller.
        !          2631:  */
        !          2632: const htmlEntityDesc *
        !          2633: htmlParseEntityRef(htmlParserCtxtPtr ctxt, const xmlChar **str) {
        !          2634:     const xmlChar *name;
        !          2635:     const htmlEntityDesc * ent = NULL;
        !          2636: 
        !          2637:     if (str != NULL) *str = NULL;
        !          2638:     if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
        !          2639: 
        !          2640:     if (CUR == '&') {
        !          2641:         NEXT;
        !          2642:         name = htmlParseName(ctxt);
        !          2643:        if (name == NULL) {
        !          2644:            htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
        !          2645:                         "htmlParseEntityRef: no name\n", NULL, NULL);
        !          2646:        } else {
        !          2647:            GROW;
        !          2648:            if (CUR == ';') {
        !          2649:                if (str != NULL)
        !          2650:                    *str = name;
        !          2651: 
        !          2652:                /*
        !          2653:                 * Lookup the entity in the table.
        !          2654:                 */
        !          2655:                ent = htmlEntityLookup(name);
        !          2656:                if (ent != NULL) /* OK that's ugly !!! */
        !          2657:                    NEXT;
        !          2658:            } else {
        !          2659:                htmlParseErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING,
        !          2660:                             "htmlParseEntityRef: expecting ';'\n",
        !          2661:                             NULL, NULL);
        !          2662:                if (str != NULL)
        !          2663:                    *str = name;
        !          2664:            }
        !          2665:        }
        !          2666:     }
        !          2667:     return(ent);
        !          2668: }
        !          2669: 
        !          2670: /**
        !          2671:  * htmlParseAttValue:
        !          2672:  * @ctxt:  an HTML parser context
        !          2673:  *
        !          2674:  * parse a value for an attribute
        !          2675:  * Note: the parser won't do substitution of entities here, this
        !          2676:  * will be handled later in xmlStringGetNodeList, unless it was
        !          2677:  * asked for ctxt->replaceEntities != 0
        !          2678:  *
        !          2679:  * Returns the AttValue parsed or NULL.
        !          2680:  */
        !          2681: 
        !          2682: static xmlChar *
        !          2683: htmlParseAttValue(htmlParserCtxtPtr ctxt) {
        !          2684:     xmlChar *ret = NULL;
        !          2685: 
        !          2686:     if (CUR == '"') {
        !          2687:         NEXT;
        !          2688:        ret = htmlParseHTMLAttribute(ctxt, '"');
        !          2689:         if (CUR != '"') {
        !          2690:            htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
        !          2691:                         "AttValue: \" expected\n", NULL, NULL);
        !          2692:        } else
        !          2693:            NEXT;
        !          2694:     } else if (CUR == '\'') {
        !          2695:         NEXT;
        !          2696:        ret = htmlParseHTMLAttribute(ctxt, '\'');
        !          2697:         if (CUR != '\'') {
        !          2698:            htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
        !          2699:                         "AttValue: ' expected\n", NULL, NULL);
        !          2700:        } else
        !          2701:            NEXT;
        !          2702:     } else {
        !          2703:         /*
        !          2704:         * That's an HTMLism, the attribute value may not be quoted
        !          2705:         */
        !          2706:        ret = htmlParseHTMLAttribute(ctxt, 0);
        !          2707:        if (ret == NULL) {
        !          2708:            htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
        !          2709:                         "AttValue: no value found\n", NULL, NULL);
        !          2710:        }
        !          2711:     }
        !          2712:     return(ret);
        !          2713: }
        !          2714: 
        !          2715: /**
        !          2716:  * htmlParseSystemLiteral:
        !          2717:  * @ctxt:  an HTML parser context
        !          2718:  *
        !          2719:  * parse an HTML Literal
        !          2720:  *
        !          2721:  * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
        !          2722:  *
        !          2723:  * Returns the SystemLiteral parsed or NULL
        !          2724:  */
        !          2725: 
        !          2726: static xmlChar *
        !          2727: htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
        !          2728:     const xmlChar *q;
        !          2729:     xmlChar *ret = NULL;
        !          2730: 
        !          2731:     if (CUR == '"') {
        !          2732:         NEXT;
        !          2733:        q = CUR_PTR;
        !          2734:        while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
        !          2735:            NEXT;
        !          2736:        if (!IS_CHAR_CH(CUR)) {
        !          2737:            htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
        !          2738:                         "Unfinished SystemLiteral\n", NULL, NULL);
        !          2739:        } else {
        !          2740:            ret = xmlStrndup(q, CUR_PTR - q);
        !          2741:            NEXT;
        !          2742:         }
        !          2743:     } else if (CUR == '\'') {
        !          2744:         NEXT;
        !          2745:        q = CUR_PTR;
        !          2746:        while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
        !          2747:            NEXT;
        !          2748:        if (!IS_CHAR_CH(CUR)) {
        !          2749:            htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
        !          2750:                         "Unfinished SystemLiteral\n", NULL, NULL);
        !          2751:        } else {
        !          2752:            ret = xmlStrndup(q, CUR_PTR - q);
        !          2753:            NEXT;
        !          2754:         }
        !          2755:     } else {
        !          2756:        htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
        !          2757:                     " or ' expected\n", NULL, NULL);
        !          2758:     }
        !          2759: 
        !          2760:     return(ret);
        !          2761: }
        !          2762: 
        !          2763: /**
        !          2764:  * htmlParsePubidLiteral:
        !          2765:  * @ctxt:  an HTML parser context
        !          2766:  *
        !          2767:  * parse an HTML public literal
        !          2768:  *
        !          2769:  * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
        !          2770:  *
        !          2771:  * Returns the PubidLiteral parsed or NULL.
        !          2772:  */
        !          2773: 
        !          2774: static xmlChar *
        !          2775: htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
        !          2776:     const xmlChar *q;
        !          2777:     xmlChar *ret = NULL;
        !          2778:     /*
        !          2779:      * Name ::= (Letter | '_') (NameChar)*
        !          2780:      */
        !          2781:     if (CUR == '"') {
        !          2782:         NEXT;
        !          2783:        q = CUR_PTR;
        !          2784:        while (IS_PUBIDCHAR_CH(CUR)) NEXT;
        !          2785:        if (CUR != '"') {
        !          2786:            htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
        !          2787:                         "Unfinished PubidLiteral\n", NULL, NULL);
        !          2788:        } else {
        !          2789:            ret = xmlStrndup(q, CUR_PTR - q);
        !          2790:            NEXT;
        !          2791:        }
        !          2792:     } else if (CUR == '\'') {
        !          2793:         NEXT;
        !          2794:        q = CUR_PTR;
        !          2795:        while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\''))
        !          2796:            NEXT;
        !          2797:        if (CUR != '\'') {
        !          2798:            htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
        !          2799:                         "Unfinished PubidLiteral\n", NULL, NULL);
        !          2800:        } else {
        !          2801:            ret = xmlStrndup(q, CUR_PTR - q);
        !          2802:            NEXT;
        !          2803:        }
        !          2804:     } else {
        !          2805:        htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
        !          2806:                     "PubidLiteral \" or ' expected\n", NULL, NULL);
        !          2807:     }
        !          2808: 
        !          2809:     return(ret);
        !          2810: }
        !          2811: 
        !          2812: /**
        !          2813:  * htmlParseScript:
        !          2814:  * @ctxt:  an HTML parser context
        !          2815:  *
        !          2816:  * parse the content of an HTML SCRIPT or STYLE element
        !          2817:  * http://www.w3.org/TR/html4/sgml/dtd.html#Script
        !          2818:  * http://www.w3.org/TR/html4/sgml/dtd.html#StyleSheet
        !          2819:  * http://www.w3.org/TR/html4/types.html#type-script
        !          2820:  * http://www.w3.org/TR/html4/types.html#h-6.15
        !          2821:  * http://www.w3.org/TR/html4/appendix/notes.html#h-B.3.2.1
        !          2822:  *
        !          2823:  * Script data ( %Script; in the DTD) can be the content of the SCRIPT
        !          2824:  * element and the value of intrinsic event attributes. User agents must
        !          2825:  * not evaluate script data as HTML markup but instead must pass it on as
        !          2826:  * data to a script engine.
        !          2827:  * NOTES:
        !          2828:  * - The content is passed like CDATA
        !          2829:  * - the attributes for style and scripting "onXXX" are also described
        !          2830:  *   as CDATA but SGML allows entities references in attributes so their
        !          2831:  *   processing is identical as other attributes
        !          2832:  */
        !          2833: static void
        !          2834: htmlParseScript(htmlParserCtxtPtr ctxt) {
        !          2835:     xmlChar buf[HTML_PARSER_BIG_BUFFER_SIZE + 5];
        !          2836:     int nbchar = 0;
        !          2837:     int cur,l;
        !          2838: 
        !          2839:     SHRINK;
        !          2840:     cur = CUR_CHAR(l);
        !          2841:     while (IS_CHAR_CH(cur)) {
        !          2842:        if ((cur == '<') && (NXT(1) == '/')) {
        !          2843:             /*
        !          2844:              * One should break here, the specification is clear:
        !          2845:              * Authors should therefore escape "</" within the content.
        !          2846:              * Escape mechanisms are specific to each scripting or
        !          2847:              * style sheet language.
        !          2848:              *
        !          2849:              * In recovery mode, only break if end tag match the
        !          2850:              * current tag, effectively ignoring all tags inside the
        !          2851:              * script/style block and treating the entire block as
        !          2852:              * CDATA.
        !          2853:              */
        !          2854:             if (ctxt->recovery) {
        !          2855:                 if (xmlStrncasecmp(ctxt->name, ctxt->input->cur+2,
        !          2856:                                   xmlStrlen(ctxt->name)) == 0)
        !          2857:                 {
        !          2858:                     break; /* while */
        !          2859:                 } else {
        !          2860:                    htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
        !          2861:                                 "Element %s embeds close tag\n",
        !          2862:                                 ctxt->name, NULL);
        !          2863:                }
        !          2864:             } else {
        !          2865:                 if (((NXT(2) >= 'A') && (NXT(2) <= 'Z')) ||
        !          2866:                     ((NXT(2) >= 'a') && (NXT(2) <= 'z')))
        !          2867:                 {
        !          2868:                     break; /* while */
        !          2869:                 }
        !          2870:             }
        !          2871:        }
        !          2872:        COPY_BUF(l,buf,nbchar,cur);
        !          2873:        if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
        !          2874:            if (ctxt->sax->cdataBlock!= NULL) {
        !          2875:                /*
        !          2876:                 * Insert as CDATA, which is the same as HTML_PRESERVE_NODE
        !          2877:                 */
        !          2878:                ctxt->sax->cdataBlock(ctxt->userData, buf, nbchar);
        !          2879:            } else if (ctxt->sax->characters != NULL) {
        !          2880:                ctxt->sax->characters(ctxt->userData, buf, nbchar);
        !          2881:            }
        !          2882:            nbchar = 0;
        !          2883:        }
        !          2884:        GROW;
        !          2885:        NEXTL(l);
        !          2886:        cur = CUR_CHAR(l);
        !          2887:     }
        !          2888: 
        !          2889:     if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) {
        !          2890:         htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
        !          2891:                     "Invalid char in CDATA 0x%X\n", cur);
        !          2892:         if (ctxt->input->cur < ctxt->input->end) {
        !          2893:             NEXT;
        !          2894:         }
        !          2895:     }
        !          2896: 
        !          2897:     if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) {
        !          2898:        if (ctxt->sax->cdataBlock!= NULL) {
        !          2899:            /*
        !          2900:             * Insert as CDATA, which is the same as HTML_PRESERVE_NODE
        !          2901:             */
        !          2902:            ctxt->sax->cdataBlock(ctxt->userData, buf, nbchar);
        !          2903:        } else if (ctxt->sax->characters != NULL) {
        !          2904:            ctxt->sax->characters(ctxt->userData, buf, nbchar);
        !          2905:        }
        !          2906:     }
        !          2907: }
        !          2908: 
        !          2909: 
        !          2910: /**
        !          2911:  * htmlParseCharData:
        !          2912:  * @ctxt:  an HTML parser context
        !          2913:  *
        !          2914:  * parse a CharData section.
        !          2915:  * if we are within a CDATA section ']]>' marks an end of section.
        !          2916:  *
        !          2917:  * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
        !          2918:  */
        !          2919: 
        !          2920: static void
        !          2921: htmlParseCharData(htmlParserCtxtPtr ctxt) {
        !          2922:     xmlChar buf[HTML_PARSER_BIG_BUFFER_SIZE + 5];
        !          2923:     int nbchar = 0;
        !          2924:     int cur, l;
        !          2925:     int chunk = 0;
        !          2926: 
        !          2927:     SHRINK;
        !          2928:     cur = CUR_CHAR(l);
        !          2929:     while (((cur != '<') || (ctxt->token == '<')) &&
        !          2930:            ((cur != '&') || (ctxt->token == '&')) &&
        !          2931:           (cur != 0)) {
        !          2932:        if (!(IS_CHAR(cur))) {
        !          2933:            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
        !          2934:                        "Invalid char in CDATA 0x%X\n", cur);
        !          2935:        } else {
        !          2936:            COPY_BUF(l,buf,nbchar,cur);
        !          2937:        }
        !          2938:        if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
        !          2939:            /*
        !          2940:             * Ok the segment is to be consumed as chars.
        !          2941:             */
        !          2942:            if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
        !          2943:                if (areBlanks(ctxt, buf, nbchar)) {
        !          2944:                    if (ctxt->sax->ignorableWhitespace != NULL)
        !          2945:                        ctxt->sax->ignorableWhitespace(ctxt->userData,
        !          2946:                                                       buf, nbchar);
        !          2947:                } else {
        !          2948:                    htmlCheckParagraph(ctxt);
        !          2949:                    if (ctxt->sax->characters != NULL)
        !          2950:                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
        !          2951:                }
        !          2952:            }
        !          2953:            nbchar = 0;
        !          2954:        }
        !          2955:        NEXTL(l);
        !          2956:         chunk++;
        !          2957:         if (chunk > HTML_PARSER_BUFFER_SIZE) {
        !          2958:             chunk = 0;
        !          2959:             SHRINK;
        !          2960:             GROW;
        !          2961:         }
        !          2962:        cur = CUR_CHAR(l);
        !          2963:        if (cur == 0) {
        !          2964:            SHRINK;
        !          2965:            GROW;
        !          2966:            cur = CUR_CHAR(l);
        !          2967:        }
        !          2968:     }
        !          2969:     if (nbchar != 0) {
        !          2970:         buf[nbchar] = 0;
        !          2971: 
        !          2972:        /*
        !          2973:         * Ok the segment is to be consumed as chars.
        !          2974:         */
        !          2975:        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
        !          2976:            if (areBlanks(ctxt, buf, nbchar)) {
        !          2977:                if (ctxt->sax->ignorableWhitespace != NULL)
        !          2978:                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
        !          2979:            } else {
        !          2980:                htmlCheckParagraph(ctxt);
        !          2981:                if (ctxt->sax->characters != NULL)
        !          2982:                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
        !          2983:            }
        !          2984:        }
        !          2985:     } else {
        !          2986:        /*
        !          2987:         * Loop detection
        !          2988:         */
        !          2989:        if (cur == 0)
        !          2990:            ctxt->instate = XML_PARSER_EOF;
        !          2991:     }
        !          2992: }
        !          2993: 
        !          2994: /**
        !          2995:  * htmlParseExternalID:
        !          2996:  * @ctxt:  an HTML parser context
        !          2997:  * @publicID:  a xmlChar** receiving PubidLiteral
        !          2998:  *
        !          2999:  * Parse an External ID or a Public ID
        !          3000:  *
        !          3001:  * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
        !          3002:  *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
        !          3003:  *
        !          3004:  * [83] PublicID ::= 'PUBLIC' S PubidLiteral
        !          3005:  *
        !          3006:  * Returns the function returns SystemLiteral and in the second
        !          3007:  *                case publicID receives PubidLiteral, is strict is off
        !          3008:  *                it is possible to return NULL and have publicID set.
        !          3009:  */
        !          3010: 
        !          3011: static xmlChar *
        !          3012: htmlParseExternalID(htmlParserCtxtPtr ctxt, xmlChar **publicID) {
        !          3013:     xmlChar *URI = NULL;
        !          3014: 
        !          3015:     if ((UPPER == 'S') && (UPP(1) == 'Y') &&
        !          3016:          (UPP(2) == 'S') && (UPP(3) == 'T') &&
        !          3017:         (UPP(4) == 'E') && (UPP(5) == 'M')) {
        !          3018:         SKIP(6);
        !          3019:        if (!IS_BLANK_CH(CUR)) {
        !          3020:            htmlParseErr(ctxt, XML_ERR_SPACE_REQUIRED,
        !          3021:                         "Space required after 'SYSTEM'\n", NULL, NULL);
        !          3022:        }
        !          3023:         SKIP_BLANKS;
        !          3024:        URI = htmlParseSystemLiteral(ctxt);
        !          3025:        if (URI == NULL) {
        !          3026:            htmlParseErr(ctxt, XML_ERR_URI_REQUIRED,
        !          3027:                         "htmlParseExternalID: SYSTEM, no URI\n", NULL, NULL);
        !          3028:         }
        !          3029:     } else if ((UPPER == 'P') && (UPP(1) == 'U') &&
        !          3030:               (UPP(2) == 'B') && (UPP(3) == 'L') &&
        !          3031:               (UPP(4) == 'I') && (UPP(5) == 'C')) {
        !          3032:         SKIP(6);
        !          3033:        if (!IS_BLANK_CH(CUR)) {
        !          3034:            htmlParseErr(ctxt, XML_ERR_SPACE_REQUIRED,
        !          3035:                         "Space required after 'PUBLIC'\n", NULL, NULL);
        !          3036:        }
        !          3037:         SKIP_BLANKS;
        !          3038:        *publicID = htmlParsePubidLiteral(ctxt);
        !          3039:        if (*publicID == NULL) {
        !          3040:            htmlParseErr(ctxt, XML_ERR_PUBID_REQUIRED,
        !          3041:                         "htmlParseExternalID: PUBLIC, no Public Identifier\n",
        !          3042:                         NULL, NULL);
        !          3043:        }
        !          3044:         SKIP_BLANKS;
        !          3045:         if ((CUR == '"') || (CUR == '\'')) {
        !          3046:            URI = htmlParseSystemLiteral(ctxt);
        !          3047:        }
        !          3048:     }
        !          3049:     return(URI);
        !          3050: }
        !          3051: 
        !          3052: /**
        !          3053:  * xmlParsePI:
        !          3054:  * @ctxt:  an XML parser context
        !          3055:  *
        !          3056:  * parse an XML Processing Instruction.
        !          3057:  *
        !          3058:  * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
        !          3059:  */
        !          3060: static void
        !          3061: htmlParsePI(htmlParserCtxtPtr ctxt) {
        !          3062:     xmlChar *buf = NULL;
        !          3063:     int len = 0;
        !          3064:     int size = HTML_PARSER_BUFFER_SIZE;
        !          3065:     int cur, l;
        !          3066:     const xmlChar *target;
        !          3067:     xmlParserInputState state;
        !          3068:     int count = 0;
        !          3069: 
        !          3070:     if ((RAW == '<') && (NXT(1) == '?')) {
        !          3071:        state = ctxt->instate;
        !          3072:         ctxt->instate = XML_PARSER_PI;
        !          3073:        /*
        !          3074:         * this is a Processing Instruction.
        !          3075:         */
        !          3076:        SKIP(2);
        !          3077:        SHRINK;
        !          3078: 
        !          3079:        /*
        !          3080:         * Parse the target name and check for special support like
        !          3081:         * namespace.
        !          3082:         */
        !          3083:         target = htmlParseName(ctxt);
        !          3084:        if (target != NULL) {
        !          3085:            if (RAW == '>') {
        !          3086:                SKIP(1);
        !          3087: 
        !          3088:                /*
        !          3089:                 * SAX: PI detected.
        !          3090:                 */
        !          3091:                if ((ctxt->sax) && (!ctxt->disableSAX) &&
        !          3092:                    (ctxt->sax->processingInstruction != NULL))
        !          3093:                    ctxt->sax->processingInstruction(ctxt->userData,
        !          3094:                                                     target, NULL);
        !          3095:                ctxt->instate = state;
        !          3096:                return;
        !          3097:            }
        !          3098:            buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
        !          3099:            if (buf == NULL) {
        !          3100:                htmlErrMemory(ctxt, NULL);
        !          3101:                ctxt->instate = state;
        !          3102:                return;
        !          3103:            }
        !          3104:            cur = CUR;
        !          3105:            if (!IS_BLANK(cur)) {
        !          3106:                htmlParseErr(ctxt, XML_ERR_SPACE_REQUIRED,
        !          3107:                          "ParsePI: PI %s space expected\n", target, NULL);
        !          3108:            }
        !          3109:             SKIP_BLANKS;
        !          3110:            cur = CUR_CHAR(l);
        !          3111:            while (IS_CHAR(cur) && (cur != '>')) {
        !          3112:                if (len + 5 >= size) {
        !          3113:                    xmlChar *tmp;
        !          3114: 
        !          3115:                    size *= 2;
        !          3116:                    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
        !          3117:                    if (tmp == NULL) {
        !          3118:                        htmlErrMemory(ctxt, NULL);
        !          3119:                        xmlFree(buf);
        !          3120:                        ctxt->instate = state;
        !          3121:                        return;
        !          3122:                    }
        !          3123:                    buf = tmp;
        !          3124:                }
        !          3125:                count++;
        !          3126:                if (count > 50) {
        !          3127:                    GROW;
        !          3128:                    count = 0;
        !          3129:                }
        !          3130:                COPY_BUF(l,buf,len,cur);
        !          3131:                NEXTL(l);
        !          3132:                cur = CUR_CHAR(l);
        !          3133:                if (cur == 0) {
        !          3134:                    SHRINK;
        !          3135:                    GROW;
        !          3136:                    cur = CUR_CHAR(l);
        !          3137:                }
        !          3138:            }
        !          3139:            buf[len] = 0;
        !          3140:            if (cur != '>') {
        !          3141:                htmlParseErr(ctxt, XML_ERR_PI_NOT_FINISHED,
        !          3142:                      "ParsePI: PI %s never end ...\n", target, NULL);
        !          3143:            } else {
        !          3144:                SKIP(1);
        !          3145: 
        !          3146:                /*
        !          3147:                 * SAX: PI detected.
        !          3148:                 */
        !          3149:                if ((ctxt->sax) && (!ctxt->disableSAX) &&
        !          3150:                    (ctxt->sax->processingInstruction != NULL))
        !          3151:                    ctxt->sax->processingInstruction(ctxt->userData,
        !          3152:                                                     target, buf);
        !          3153:            }
        !          3154:            xmlFree(buf);
        !          3155:        } else {
        !          3156:            htmlParseErr(ctxt, XML_ERR_PI_NOT_STARTED,
        !          3157:                          "PI is not started correctly", NULL, NULL);
        !          3158:        }
        !          3159:        ctxt->instate = state;
        !          3160:     }
        !          3161: }
        !          3162: 
        !          3163: /**
        !          3164:  * htmlParseComment:
        !          3165:  * @ctxt:  an HTML parser context
        !          3166:  *
        !          3167:  * Parse an XML (SGML) comment <!-- .... -->
        !          3168:  *
        !          3169:  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
        !          3170:  */
        !          3171: static void
        !          3172: htmlParseComment(htmlParserCtxtPtr ctxt) {
        !          3173:     xmlChar *buf = NULL;
        !          3174:     int len;
        !          3175:     int size = HTML_PARSER_BUFFER_SIZE;
        !          3176:     int q, ql;
        !          3177:     int r, rl;
        !          3178:     int cur, l;
        !          3179:     xmlParserInputState state;
        !          3180: 
        !          3181:     /*
        !          3182:      * Check that there is a comment right here.
        !          3183:      */
        !          3184:     if ((RAW != '<') || (NXT(1) != '!') ||
        !          3185:         (NXT(2) != '-') || (NXT(3) != '-')) return;
        !          3186: 
        !          3187:     state = ctxt->instate;
        !          3188:     ctxt->instate = XML_PARSER_COMMENT;
        !          3189:     SHRINK;
        !          3190:     SKIP(4);
        !          3191:     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
        !          3192:     if (buf == NULL) {
        !          3193:         htmlErrMemory(ctxt, "buffer allocation failed\n");
        !          3194:        ctxt->instate = state;
        !          3195:        return;
        !          3196:     }
        !          3197:     q = CUR_CHAR(ql);
        !          3198:     NEXTL(ql);
        !          3199:     r = CUR_CHAR(rl);
        !          3200:     NEXTL(rl);
        !          3201:     cur = CUR_CHAR(l);
        !          3202:     len = 0;
        !          3203:     while (IS_CHAR(cur) &&
        !          3204:            ((cur != '>') ||
        !          3205:            (r != '-') || (q != '-'))) {
        !          3206:        if (len + 5 >= size) {
        !          3207:            xmlChar *tmp;
        !          3208: 
        !          3209:            size *= 2;
        !          3210:            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
        !          3211:            if (tmp == NULL) {
        !          3212:                xmlFree(buf);
        !          3213:                htmlErrMemory(ctxt, "growing buffer failed\n");
        !          3214:                ctxt->instate = state;
        !          3215:                return;
        !          3216:            }
        !          3217:            buf = tmp;
        !          3218:        }
        !          3219:        COPY_BUF(ql,buf,len,q);
        !          3220:        q = r;
        !          3221:        ql = rl;
        !          3222:        r = cur;
        !          3223:        rl = l;
        !          3224:        NEXTL(l);
        !          3225:        cur = CUR_CHAR(l);
        !          3226:        if (cur == 0) {
        !          3227:            SHRINK;
        !          3228:            GROW;
        !          3229:            cur = CUR_CHAR(l);
        !          3230:        }
        !          3231:     }
        !          3232:     buf[len] = 0;
        !          3233:     if (!IS_CHAR(cur)) {
        !          3234:        htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
        !          3235:                     "Comment not terminated \n<!--%.50s\n", buf, NULL);
        !          3236:        xmlFree(buf);
        !          3237:     } else {
        !          3238:         NEXT;
        !          3239:        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
        !          3240:            (!ctxt->disableSAX))
        !          3241:            ctxt->sax->comment(ctxt->userData, buf);
        !          3242:        xmlFree(buf);
        !          3243:     }
        !          3244:     ctxt->instate = state;
        !          3245: }
        !          3246: 
        !          3247: /**
        !          3248:  * htmlParseCharRef:
        !          3249:  * @ctxt:  an HTML parser context
        !          3250:  *
        !          3251:  * parse Reference declarations
        !          3252:  *
        !          3253:  * [66] CharRef ::= '&#' [0-9]+ ';' |
        !          3254:  *                  '&#x' [0-9a-fA-F]+ ';'
        !          3255:  *
        !          3256:  * Returns the value parsed (as an int)
        !          3257:  */
        !          3258: int
        !          3259: htmlParseCharRef(htmlParserCtxtPtr ctxt) {
        !          3260:     int val = 0;
        !          3261: 
        !          3262:     if ((ctxt == NULL) || (ctxt->input == NULL)) {
        !          3263:        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          3264:                     "htmlParseCharRef: context error\n",
        !          3265:                     NULL, NULL);
        !          3266:         return(0);
        !          3267:     }
        !          3268:     if ((CUR == '&') && (NXT(1) == '#') &&
        !          3269:         ((NXT(2) == 'x') || NXT(2) == 'X')) {
        !          3270:        SKIP(3);
        !          3271:        while (CUR != ';') {
        !          3272:            if ((CUR >= '0') && (CUR <= '9'))
        !          3273:                val = val * 16 + (CUR - '0');
        !          3274:            else if ((CUR >= 'a') && (CUR <= 'f'))
        !          3275:                val = val * 16 + (CUR - 'a') + 10;
        !          3276:            else if ((CUR >= 'A') && (CUR <= 'F'))
        !          3277:                val = val * 16 + (CUR - 'A') + 10;
        !          3278:            else {
        !          3279:                htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF,
        !          3280:                             "htmlParseCharRef: missing semicolon\n",
        !          3281:                             NULL, NULL);
        !          3282:                break;
        !          3283:            }
        !          3284:            NEXT;
        !          3285:        }
        !          3286:        if (CUR == ';')
        !          3287:            NEXT;
        !          3288:     } else if  ((CUR == '&') && (NXT(1) == '#')) {
        !          3289:        SKIP(2);
        !          3290:        while (CUR != ';') {
        !          3291:            if ((CUR >= '0') && (CUR <= '9'))
        !          3292:                val = val * 10 + (CUR - '0');
        !          3293:            else {
        !          3294:                htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF,
        !          3295:                             "htmlParseCharRef: missing semicolon\n",
        !          3296:                             NULL, NULL);
        !          3297:                break;
        !          3298:            }
        !          3299:            NEXT;
        !          3300:        }
        !          3301:        if (CUR == ';')
        !          3302:            NEXT;
        !          3303:     } else {
        !          3304:        htmlParseErr(ctxt, XML_ERR_INVALID_CHARREF,
        !          3305:                     "htmlParseCharRef: invalid value\n", NULL, NULL);
        !          3306:     }
        !          3307:     /*
        !          3308:      * Check the value IS_CHAR ...
        !          3309:      */
        !          3310:     if (IS_CHAR(val)) {
        !          3311:         return(val);
        !          3312:     } else {
        !          3313:        htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
        !          3314:                        "htmlParseCharRef: invalid xmlChar value %d\n",
        !          3315:                        val);
        !          3316:     }
        !          3317:     return(0);
        !          3318: }
        !          3319: 
        !          3320: 
        !          3321: /**
        !          3322:  * htmlParseDocTypeDecl:
        !          3323:  * @ctxt:  an HTML parser context
        !          3324:  *
        !          3325:  * parse a DOCTYPE declaration
        !          3326:  *
        !          3327:  * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
        !          3328:  *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
        !          3329:  */
        !          3330: 
        !          3331: static void
        !          3332: htmlParseDocTypeDecl(htmlParserCtxtPtr ctxt) {
        !          3333:     const xmlChar *name;
        !          3334:     xmlChar *ExternalID = NULL;
        !          3335:     xmlChar *URI = NULL;
        !          3336: 
        !          3337:     /*
        !          3338:      * We know that '<!DOCTYPE' has been detected.
        !          3339:      */
        !          3340:     SKIP(9);
        !          3341: 
        !          3342:     SKIP_BLANKS;
        !          3343: 
        !          3344:     /*
        !          3345:      * Parse the DOCTYPE name.
        !          3346:      */
        !          3347:     name = htmlParseName(ctxt);
        !          3348:     if (name == NULL) {
        !          3349:        htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
        !          3350:                     "htmlParseDocTypeDecl : no DOCTYPE name !\n",
        !          3351:                     NULL, NULL);
        !          3352:     }
        !          3353:     /*
        !          3354:      * Check that upper(name) == "HTML" !!!!!!!!!!!!!
        !          3355:      */
        !          3356: 
        !          3357:     SKIP_BLANKS;
        !          3358: 
        !          3359:     /*
        !          3360:      * Check for SystemID and ExternalID
        !          3361:      */
        !          3362:     URI = htmlParseExternalID(ctxt, &ExternalID);
        !          3363:     SKIP_BLANKS;
        !          3364: 
        !          3365:     /*
        !          3366:      * We should be at the end of the DOCTYPE declaration.
        !          3367:      */
        !          3368:     if (CUR != '>') {
        !          3369:        htmlParseErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED,
        !          3370:                     "DOCTYPE improperly terminated\n", NULL, NULL);
        !          3371:         /* We shouldn't try to resynchronize ... */
        !          3372:     }
        !          3373:     NEXT;
        !          3374: 
        !          3375:     /*
        !          3376:      * Create or update the document accordingly to the DOCTYPE
        !          3377:      */
        !          3378:     if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
        !          3379:        (!ctxt->disableSAX))
        !          3380:        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
        !          3381: 
        !          3382:     /*
        !          3383:      * Cleanup, since we don't use all those identifiers
        !          3384:      */
        !          3385:     if (URI != NULL) xmlFree(URI);
        !          3386:     if (ExternalID != NULL) xmlFree(ExternalID);
        !          3387: }
        !          3388: 
        !          3389: /**
        !          3390:  * htmlParseAttribute:
        !          3391:  * @ctxt:  an HTML parser context
        !          3392:  * @value:  a xmlChar ** used to store the value of the attribute
        !          3393:  *
        !          3394:  * parse an attribute
        !          3395:  *
        !          3396:  * [41] Attribute ::= Name Eq AttValue
        !          3397:  *
        !          3398:  * [25] Eq ::= S? '=' S?
        !          3399:  *
        !          3400:  * With namespace:
        !          3401:  *
        !          3402:  * [NS 11] Attribute ::= QName Eq AttValue
        !          3403:  *
        !          3404:  * Also the case QName == xmlns:??? is handled independently as a namespace
        !          3405:  * definition.
        !          3406:  *
        !          3407:  * Returns the attribute name, and the value in *value.
        !          3408:  */
        !          3409: 
        !          3410: static const xmlChar *
        !          3411: htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) {
        !          3412:     const xmlChar *name;
        !          3413:     xmlChar *val = NULL;
        !          3414: 
        !          3415:     *value = NULL;
        !          3416:     name = htmlParseHTMLName(ctxt);
        !          3417:     if (name == NULL) {
        !          3418:        htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
        !          3419:                     "error parsing attribute name\n", NULL, NULL);
        !          3420:         return(NULL);
        !          3421:     }
        !          3422: 
        !          3423:     /*
        !          3424:      * read the value
        !          3425:      */
        !          3426:     SKIP_BLANKS;
        !          3427:     if (CUR == '=') {
        !          3428:         NEXT;
        !          3429:        SKIP_BLANKS;
        !          3430:        val = htmlParseAttValue(ctxt);
        !          3431:     }
        !          3432: 
        !          3433:     *value = val;
        !          3434:     return(name);
        !          3435: }
        !          3436: 
        !          3437: /**
        !          3438:  * htmlCheckEncoding:
        !          3439:  * @ctxt:  an HTML parser context
        !          3440:  * @attvalue: the attribute value
        !          3441:  *
        !          3442:  * Checks an http-equiv attribute from a Meta tag to detect
        !          3443:  * the encoding
        !          3444:  * If a new encoding is detected the parser is switched to decode
        !          3445:  * it and pass UTF8
        !          3446:  */
        !          3447: static void
        !          3448: htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) {
        !          3449:     const xmlChar *encoding;
        !          3450: 
        !          3451:     if ((ctxt == NULL) || (attvalue == NULL))
        !          3452:        return;
        !          3453: 
        !          3454:     /* do not change encoding */
        !          3455:     if (ctxt->input->encoding != NULL)
        !          3456:         return;
        !          3457: 
        !          3458:     encoding = xmlStrcasestr(attvalue, BAD_CAST"charset=");
        !          3459:     if (encoding != NULL) {
        !          3460:        encoding += 8;
        !          3461:     } else {
        !          3462:        encoding = xmlStrcasestr(attvalue, BAD_CAST"charset =");
        !          3463:        if (encoding != NULL)
        !          3464:            encoding += 9;
        !          3465:     }
        !          3466:     if (encoding != NULL) {
        !          3467:        xmlCharEncoding enc;
        !          3468:        xmlCharEncodingHandlerPtr handler;
        !          3469: 
        !          3470:        while ((*encoding == ' ') || (*encoding == '\t')) encoding++;
        !          3471: 
        !          3472:        if (ctxt->input->encoding != NULL)
        !          3473:            xmlFree((xmlChar *) ctxt->input->encoding);
        !          3474:        ctxt->input->encoding = xmlStrdup(encoding);
        !          3475: 
        !          3476:        enc = xmlParseCharEncoding((const char *) encoding);
        !          3477:        /*
        !          3478:         * registered set of known encodings
        !          3479:         */
        !          3480:        if (enc != XML_CHAR_ENCODING_ERROR) {
        !          3481:            if (((enc == XML_CHAR_ENCODING_UTF16LE) ||
        !          3482:                 (enc == XML_CHAR_ENCODING_UTF16BE) ||
        !          3483:                 (enc == XML_CHAR_ENCODING_UCS4LE) ||
        !          3484:                 (enc == XML_CHAR_ENCODING_UCS4BE)) &&
        !          3485:                (ctxt->input->buf != NULL) &&
        !          3486:                (ctxt->input->buf->encoder == NULL)) {
        !          3487:                htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
        !          3488:                             "htmlCheckEncoding: wrong encoding meta\n",
        !          3489:                             NULL, NULL);
        !          3490:            } else {
        !          3491:                xmlSwitchEncoding(ctxt, enc);
        !          3492:            }
        !          3493:            ctxt->charset = XML_CHAR_ENCODING_UTF8;
        !          3494:        } else {
        !          3495:            /*
        !          3496:             * fallback for unknown encodings
        !          3497:             */
        !          3498:            handler = xmlFindCharEncodingHandler((const char *) encoding);
        !          3499:            if (handler != NULL) {
        !          3500:                xmlSwitchToEncoding(ctxt, handler);
        !          3501:                ctxt->charset = XML_CHAR_ENCODING_UTF8;
        !          3502:            } else {
        !          3503:                ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
        !          3504:            }
        !          3505:        }
        !          3506: 
        !          3507:        if ((ctxt->input->buf != NULL) &&
        !          3508:            (ctxt->input->buf->encoder != NULL) &&
        !          3509:            (ctxt->input->buf->raw != NULL) &&
        !          3510:            (ctxt->input->buf->buffer != NULL)) {
        !          3511:            int nbchars;
        !          3512:            int processed;
        !          3513: 
        !          3514:            /*
        !          3515:             * convert as much as possible to the parser reading buffer.
        !          3516:             */
        !          3517:            processed = ctxt->input->cur - ctxt->input->base;
        !          3518:            xmlBufferShrink(ctxt->input->buf->buffer, processed);
        !          3519:            nbchars = xmlCharEncInFunc(ctxt->input->buf->encoder,
        !          3520:                                       ctxt->input->buf->buffer,
        !          3521:                                       ctxt->input->buf->raw);
        !          3522:            if (nbchars < 0) {
        !          3523:                htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
        !          3524:                             "htmlCheckEncoding: encoder error\n",
        !          3525:                             NULL, NULL);
        !          3526:            }
        !          3527:            ctxt->input->base =
        !          3528:            ctxt->input->cur = ctxt->input->buf->buffer->content;
        !          3529:             ctxt->input->end =
        !          3530:                           &ctxt->input->base[ctxt->input->buf->buffer->use];
        !          3531:        }
        !          3532:     }
        !          3533: }
        !          3534: 
        !          3535: /**
        !          3536:  * htmlCheckMeta:
        !          3537:  * @ctxt:  an HTML parser context
        !          3538:  * @atts:  the attributes values
        !          3539:  *
        !          3540:  * Checks an attributes from a Meta tag
        !          3541:  */
        !          3542: static void
        !          3543: htmlCheckMeta(htmlParserCtxtPtr ctxt, const xmlChar **atts) {
        !          3544:     int i;
        !          3545:     const xmlChar *att, *value;
        !          3546:     int http = 0;
        !          3547:     const xmlChar *content = NULL;
        !          3548: 
        !          3549:     if ((ctxt == NULL) || (atts == NULL))
        !          3550:        return;
        !          3551: 
        !          3552:     i = 0;
        !          3553:     att = atts[i++];
        !          3554:     while (att != NULL) {
        !          3555:        value = atts[i++];
        !          3556:        if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"http-equiv"))
        !          3557:         && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
        !          3558:            http = 1;
        !          3559:        else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content")))
        !          3560:            content = value;
        !          3561:        att = atts[i++];
        !          3562:     }
        !          3563:     if ((http) && (content != NULL))
        !          3564:        htmlCheckEncoding(ctxt, content);
        !          3565: 
        !          3566: }
        !          3567: 
        !          3568: /**
        !          3569:  * htmlParseStartTag:
        !          3570:  * @ctxt:  an HTML parser context
        !          3571:  *
        !          3572:  * parse a start of tag either for rule element or
        !          3573:  * EmptyElement. In both case we don't parse the tag closing chars.
        !          3574:  *
        !          3575:  * [40] STag ::= '<' Name (S Attribute)* S? '>'
        !          3576:  *
        !          3577:  * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
        !          3578:  *
        !          3579:  * With namespace:
        !          3580:  *
        !          3581:  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
        !          3582:  *
        !          3583:  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
        !          3584:  *
        !          3585:  * Returns 0 in case of success, -1 in case of error and 1 if discarded
        !          3586:  */
        !          3587: 
        !          3588: static int
        !          3589: htmlParseStartTag(htmlParserCtxtPtr ctxt) {
        !          3590:     const xmlChar *name;
        !          3591:     const xmlChar *attname;
        !          3592:     xmlChar *attvalue;
        !          3593:     const xmlChar **atts;
        !          3594:     int nbatts = 0;
        !          3595:     int maxatts;
        !          3596:     int meta = 0;
        !          3597:     int i;
        !          3598:     int discardtag = 0;
        !          3599: 
        !          3600:     if (ctxt->instate == XML_PARSER_EOF)
        !          3601:         return(-1);
        !          3602:     if ((ctxt == NULL) || (ctxt->input == NULL)) {
        !          3603:        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          3604:                     "htmlParseStartTag: context error\n", NULL, NULL);
        !          3605:        return -1;
        !          3606:     }
        !          3607:     if (CUR != '<') return -1;
        !          3608:     NEXT;
        !          3609: 
        !          3610:     atts = ctxt->atts;
        !          3611:     maxatts = ctxt->maxatts;
        !          3612: 
        !          3613:     GROW;
        !          3614:     name = htmlParseHTMLName(ctxt);
        !          3615:     if (name == NULL) {
        !          3616:        htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
        !          3617:                     "htmlParseStartTag: invalid element name\n",
        !          3618:                     NULL, NULL);
        !          3619:        /* Dump the bogus tag like browsers do */
        !          3620:        while ((IS_CHAR_CH(CUR)) && (CUR != '>') &&
        !          3621:                (ctxt->instate != XML_PARSER_EOF))
        !          3622:            NEXT;
        !          3623:         return -1;
        !          3624:     }
        !          3625:     if (xmlStrEqual(name, BAD_CAST"meta"))
        !          3626:        meta = 1;
        !          3627: 
        !          3628:     /*
        !          3629:      * Check for auto-closure of HTML elements.
        !          3630:      */
        !          3631:     htmlAutoClose(ctxt, name);
        !          3632: 
        !          3633:     /*
        !          3634:      * Check for implied HTML elements.
        !          3635:      */
        !          3636:     htmlCheckImplied(ctxt, name);
        !          3637: 
        !          3638:     /*
        !          3639:      * Avoid html at any level > 0, head at any level != 1
        !          3640:      * or any attempt to recurse body
        !          3641:      */
        !          3642:     if ((ctxt->nameNr > 0) && (xmlStrEqual(name, BAD_CAST"html"))) {
        !          3643:        htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
        !          3644:                     "htmlParseStartTag: misplaced <html> tag\n",
        !          3645:                     name, NULL);
        !          3646:        discardtag = 1;
        !          3647:        ctxt->depth++;
        !          3648:     }
        !          3649:     if ((ctxt->nameNr != 1) &&
        !          3650:        (xmlStrEqual(name, BAD_CAST"head"))) {
        !          3651:        htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
        !          3652:                     "htmlParseStartTag: misplaced <head> tag\n",
        !          3653:                     name, NULL);
        !          3654:        discardtag = 1;
        !          3655:        ctxt->depth++;
        !          3656:     }
        !          3657:     if (xmlStrEqual(name, BAD_CAST"body")) {
        !          3658:        int indx;
        !          3659:        for (indx = 0;indx < ctxt->nameNr;indx++) {
        !          3660:            if (xmlStrEqual(ctxt->nameTab[indx], BAD_CAST"body")) {
        !          3661:                htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
        !          3662:                             "htmlParseStartTag: misplaced <body> tag\n",
        !          3663:                             name, NULL);
        !          3664:                discardtag = 1;
        !          3665:                ctxt->depth++;
        !          3666:            }
        !          3667:        }
        !          3668:     }
        !          3669: 
        !          3670:     /*
        !          3671:      * Now parse the attributes, it ends up with the ending
        !          3672:      *
        !          3673:      * (S Attribute)* S?
        !          3674:      */
        !          3675:     SKIP_BLANKS;
        !          3676:     while ((IS_CHAR_CH(CUR)) &&
        !          3677:            (CUR != '>') &&
        !          3678:           ((CUR != '/') || (NXT(1) != '>'))) {
        !          3679:        long cons = ctxt->nbChars;
        !          3680: 
        !          3681:        GROW;
        !          3682:        attname = htmlParseAttribute(ctxt, &attvalue);
        !          3683:         if (attname != NULL) {
        !          3684: 
        !          3685:            /*
        !          3686:             * Well formedness requires at most one declaration of an attribute
        !          3687:             */
        !          3688:            for (i = 0; i < nbatts;i += 2) {
        !          3689:                if (xmlStrEqual(atts[i], attname)) {
        !          3690:                    htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
        !          3691:                                 "Attribute %s redefined\n", attname, NULL);
        !          3692:                    if (attvalue != NULL)
        !          3693:                        xmlFree(attvalue);
        !          3694:                    goto failed;
        !          3695:                }
        !          3696:            }
        !          3697: 
        !          3698:            /*
        !          3699:             * Add the pair to atts
        !          3700:             */
        !          3701:            if (atts == NULL) {
        !          3702:                maxatts = 22; /* allow for 10 attrs by default */
        !          3703:                atts = (const xmlChar **)
        !          3704:                       xmlMalloc(maxatts * sizeof(xmlChar *));
        !          3705:                if (atts == NULL) {
        !          3706:                    htmlErrMemory(ctxt, NULL);
        !          3707:                    if (attvalue != NULL)
        !          3708:                        xmlFree(attvalue);
        !          3709:                    goto failed;
        !          3710:                }
        !          3711:                ctxt->atts = atts;
        !          3712:                ctxt->maxatts = maxatts;
        !          3713:            } else if (nbatts + 4 > maxatts) {
        !          3714:                const xmlChar **n;
        !          3715: 
        !          3716:                maxatts *= 2;
        !          3717:                n = (const xmlChar **) xmlRealloc((void *) atts,
        !          3718:                                             maxatts * sizeof(const xmlChar *));
        !          3719:                if (n == NULL) {
        !          3720:                    htmlErrMemory(ctxt, NULL);
        !          3721:                    if (attvalue != NULL)
        !          3722:                        xmlFree(attvalue);
        !          3723:                    goto failed;
        !          3724:                }
        !          3725:                atts = n;
        !          3726:                ctxt->atts = atts;
        !          3727:                ctxt->maxatts = maxatts;
        !          3728:            }
        !          3729:            atts[nbatts++] = attname;
        !          3730:            atts[nbatts++] = attvalue;
        !          3731:            atts[nbatts] = NULL;
        !          3732:            atts[nbatts + 1] = NULL;
        !          3733:        }
        !          3734:        else {
        !          3735:            if (attvalue != NULL)
        !          3736:                xmlFree(attvalue);
        !          3737:            /* Dump the bogus attribute string up to the next blank or
        !          3738:             * the end of the tag. */
        !          3739:            while ((IS_CHAR_CH(CUR)) &&
        !          3740:                   !(IS_BLANK_CH(CUR)) && (CUR != '>') &&
        !          3741:                   ((CUR != '/') || (NXT(1) != '>')))
        !          3742:                NEXT;
        !          3743:        }
        !          3744: 
        !          3745: failed:
        !          3746:        SKIP_BLANKS;
        !          3747:         if (cons == ctxt->nbChars) {
        !          3748:            htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          3749:                         "htmlParseStartTag: problem parsing attributes\n",
        !          3750:                         NULL, NULL);
        !          3751:            break;
        !          3752:        }
        !          3753:     }
        !          3754: 
        !          3755:     /*
        !          3756:      * Handle specific association to the META tag
        !          3757:      */
        !          3758:     if (meta && (nbatts != 0))
        !          3759:        htmlCheckMeta(ctxt, atts);
        !          3760: 
        !          3761:     /*
        !          3762:      * SAX: Start of Element !
        !          3763:      */
        !          3764:     if (!discardtag) {
        !          3765:        htmlnamePush(ctxt, name);
        !          3766:        if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) {
        !          3767:            if (nbatts != 0)
        !          3768:                ctxt->sax->startElement(ctxt->userData, name, atts);
        !          3769:            else
        !          3770:                ctxt->sax->startElement(ctxt->userData, name, NULL);
        !          3771:        }
        !          3772:     }
        !          3773: 
        !          3774:     if (atts != NULL) {
        !          3775:         for (i = 1;i < nbatts;i += 2) {
        !          3776:            if (atts[i] != NULL)
        !          3777:                xmlFree((xmlChar *) atts[i]);
        !          3778:        }
        !          3779:     }
        !          3780: 
        !          3781:     return(discardtag);
        !          3782: }
        !          3783: 
        !          3784: /**
        !          3785:  * htmlParseEndTag:
        !          3786:  * @ctxt:  an HTML parser context
        !          3787:  *
        !          3788:  * parse an end of tag
        !          3789:  *
        !          3790:  * [42] ETag ::= '</' Name S? '>'
        !          3791:  *
        !          3792:  * With namespace
        !          3793:  *
        !          3794:  * [NS 9] ETag ::= '</' QName S? '>'
        !          3795:  *
        !          3796:  * Returns 1 if the current level should be closed.
        !          3797:  */
        !          3798: 
        !          3799: static int
        !          3800: htmlParseEndTag(htmlParserCtxtPtr ctxt)
        !          3801: {
        !          3802:     const xmlChar *name;
        !          3803:     const xmlChar *oldname;
        !          3804:     int i, ret;
        !          3805: 
        !          3806:     if ((CUR != '<') || (NXT(1) != '/')) {
        !          3807:         htmlParseErr(ctxt, XML_ERR_LTSLASH_REQUIRED,
        !          3808:                     "htmlParseEndTag: '</' not found\n", NULL, NULL);
        !          3809:         return (0);
        !          3810:     }
        !          3811:     SKIP(2);
        !          3812: 
        !          3813:     name = htmlParseHTMLName(ctxt);
        !          3814:     if (name == NULL)
        !          3815:         return (0);
        !          3816:     /*
        !          3817:      * We should definitely be at the ending "S? '>'" part
        !          3818:      */
        !          3819:     SKIP_BLANKS;
        !          3820:     if ((!IS_CHAR_CH(CUR)) || (CUR != '>')) {
        !          3821:         htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
        !          3822:                     "End tag : expected '>'\n", NULL, NULL);
        !          3823:        if (ctxt->recovery) {
        !          3824:            /*
        !          3825:             * We're not at the ending > !!
        !          3826:             * Error, unless in recover mode where we search forwards
        !          3827:             * until we find a >
        !          3828:             */
        !          3829:            while (CUR != '\0' && CUR != '>') NEXT;
        !          3830:            NEXT;
        !          3831:        }
        !          3832:     } else
        !          3833:         NEXT;
        !          3834: 
        !          3835:     /*
        !          3836:      * if we ignored misplaced tags in htmlParseStartTag don't pop them
        !          3837:      * out now.
        !          3838:      */
        !          3839:     if ((ctxt->depth > 0) &&
        !          3840:         (xmlStrEqual(name, BAD_CAST "html") ||
        !          3841:          xmlStrEqual(name, BAD_CAST "body") ||
        !          3842:         xmlStrEqual(name, BAD_CAST "head"))) {
        !          3843:        ctxt->depth--;
        !          3844:        return (0);
        !          3845:     }
        !          3846: 
        !          3847:     /*
        !          3848:      * If the name read is not one of the element in the parsing stack
        !          3849:      * then return, it's just an error.
        !          3850:      */
        !          3851:     for (i = (ctxt->nameNr - 1); i >= 0; i--) {
        !          3852:         if (xmlStrEqual(name, ctxt->nameTab[i]))
        !          3853:             break;
        !          3854:     }
        !          3855:     if (i < 0) {
        !          3856:         htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
        !          3857:                     "Unexpected end tag : %s\n", name, NULL);
        !          3858:         return (0);
        !          3859:     }
        !          3860: 
        !          3861: 
        !          3862:     /*
        !          3863:      * Check for auto-closure of HTML elements.
        !          3864:      */
        !          3865: 
        !          3866:     htmlAutoCloseOnClose(ctxt, name);
        !          3867: 
        !          3868:     /*
        !          3869:      * Well formedness constraints, opening and closing must match.
        !          3870:      * With the exception that the autoclose may have popped stuff out
        !          3871:      * of the stack.
        !          3872:      */
        !          3873:     if (!xmlStrEqual(name, ctxt->name)) {
        !          3874:         if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
        !          3875:             htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
        !          3876:                         "Opening and ending tag mismatch: %s and %s\n",
        !          3877:                         name, ctxt->name);
        !          3878:         }
        !          3879:     }
        !          3880: 
        !          3881:     /*
        !          3882:      * SAX: End of Tag
        !          3883:      */
        !          3884:     oldname = ctxt->name;
        !          3885:     if ((oldname != NULL) && (xmlStrEqual(oldname, name))) {
        !          3886:         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          3887:             ctxt->sax->endElement(ctxt->userData, name);
        !          3888:         htmlnamePop(ctxt);
        !          3889:         ret = 1;
        !          3890:     } else {
        !          3891:         ret = 0;
        !          3892:     }
        !          3893: 
        !          3894:     return (ret);
        !          3895: }
        !          3896: 
        !          3897: 
        !          3898: /**
        !          3899:  * htmlParseReference:
        !          3900:  * @ctxt:  an HTML parser context
        !          3901:  *
        !          3902:  * parse and handle entity references in content,
        !          3903:  * this will end-up in a call to character() since this is either a
        !          3904:  * CharRef, or a predefined entity.
        !          3905:  */
        !          3906: static void
        !          3907: htmlParseReference(htmlParserCtxtPtr ctxt) {
        !          3908:     const htmlEntityDesc * ent;
        !          3909:     xmlChar out[6];
        !          3910:     const xmlChar *name;
        !          3911:     if (CUR != '&') return;
        !          3912: 
        !          3913:     if (NXT(1) == '#') {
        !          3914:        unsigned int c;
        !          3915:        int bits, i = 0;
        !          3916: 
        !          3917:        c = htmlParseCharRef(ctxt);
        !          3918:        if (c == 0)
        !          3919:            return;
        !          3920: 
        !          3921:         if      (c <    0x80) { out[i++]= c;                bits= -6; }
        !          3922:         else if (c <   0x800) { out[i++]=((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
        !          3923:         else if (c < 0x10000) { out[i++]=((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
        !          3924:         else                  { out[i++]=((c >> 18) & 0x07) | 0xF0;  bits= 12; }
        !          3925: 
        !          3926:         for ( ; bits >= 0; bits-= 6) {
        !          3927:             out[i++]= ((c >> bits) & 0x3F) | 0x80;
        !          3928:         }
        !          3929:        out[i] = 0;
        !          3930: 
        !          3931:        htmlCheckParagraph(ctxt);
        !          3932:        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
        !          3933:            ctxt->sax->characters(ctxt->userData, out, i);
        !          3934:     } else {
        !          3935:        ent = htmlParseEntityRef(ctxt, &name);
        !          3936:        if (name == NULL) {
        !          3937:            htmlCheckParagraph(ctxt);
        !          3938:            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
        !          3939:                ctxt->sax->characters(ctxt->userData, BAD_CAST "&", 1);
        !          3940:            return;
        !          3941:        }
        !          3942:        if ((ent == NULL) || !(ent->value > 0)) {
        !          3943:            htmlCheckParagraph(ctxt);
        !          3944:            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL)) {
        !          3945:                ctxt->sax->characters(ctxt->userData, BAD_CAST "&", 1);
        !          3946:                ctxt->sax->characters(ctxt->userData, name, xmlStrlen(name));
        !          3947:                /* ctxt->sax->characters(ctxt->userData, BAD_CAST ";", 1); */
        !          3948:            }
        !          3949:        } else {
        !          3950:            unsigned int c;
        !          3951:            int bits, i = 0;
        !          3952: 
        !          3953:            c = ent->value;
        !          3954:            if      (c <    0x80)
        !          3955:                    { out[i++]= c;                bits= -6; }
        !          3956:            else if (c <   0x800)
        !          3957:                    { out[i++]=((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
        !          3958:            else if (c < 0x10000)
        !          3959:                    { out[i++]=((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
        !          3960:            else
        !          3961:                    { out[i++]=((c >> 18) & 0x07) | 0xF0;  bits= 12; }
        !          3962: 
        !          3963:            for ( ; bits >= 0; bits-= 6) {
        !          3964:                out[i++]= ((c >> bits) & 0x3F) | 0x80;
        !          3965:            }
        !          3966:            out[i] = 0;
        !          3967: 
        !          3968:            htmlCheckParagraph(ctxt);
        !          3969:            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
        !          3970:                ctxt->sax->characters(ctxt->userData, out, i);
        !          3971:        }
        !          3972:     }
        !          3973: }
        !          3974: 
        !          3975: /**
        !          3976:  * htmlParseContent:
        !          3977:  * @ctxt:  an HTML parser context
        !          3978:  *
        !          3979:  * Parse a content: comment, sub-element, reference or text.
        !          3980:  * Kept for compatibility with old code
        !          3981:  */
        !          3982: 
        !          3983: static void
        !          3984: htmlParseContent(htmlParserCtxtPtr ctxt) {
        !          3985:     xmlChar *currentNode;
        !          3986:     int depth;
        !          3987:     const xmlChar *name;
        !          3988: 
        !          3989:     currentNode = xmlStrdup(ctxt->name);
        !          3990:     depth = ctxt->nameNr;
        !          3991:     while (1) {
        !          3992:        long cons = ctxt->nbChars;
        !          3993: 
        !          3994:         GROW;
        !          3995: 
        !          3996:         if (ctxt->instate == XML_PARSER_EOF)
        !          3997:             break;
        !          3998: 
        !          3999:        /*
        !          4000:         * Our tag or one of it's parent or children is ending.
        !          4001:         */
        !          4002:         if ((CUR == '<') && (NXT(1) == '/')) {
        !          4003:            if (htmlParseEndTag(ctxt) &&
        !          4004:                ((currentNode != NULL) || (ctxt->nameNr == 0))) {
        !          4005:                if (currentNode != NULL)
        !          4006:                    xmlFree(currentNode);
        !          4007:                return;
        !          4008:            }
        !          4009:            continue; /* while */
        !          4010:         }
        !          4011: 
        !          4012:        else if ((CUR == '<') &&
        !          4013:                 ((IS_ASCII_LETTER(NXT(1))) ||
        !          4014:                  (NXT(1) == '_') || (NXT(1) == ':'))) {
        !          4015:            name = htmlParseHTMLName_nonInvasive(ctxt);
        !          4016:            if (name == NULL) {
        !          4017:                htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
        !          4018:                         "htmlParseStartTag: invalid element name\n",
        !          4019:                         NULL, NULL);
        !          4020:                /* Dump the bogus tag like browsers do */
        !          4021:         while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
        !          4022:                    NEXT;
        !          4023: 
        !          4024:                if (currentNode != NULL)
        !          4025:                    xmlFree(currentNode);
        !          4026:                return;
        !          4027:            }
        !          4028: 
        !          4029:            if (ctxt->name != NULL) {
        !          4030:                if (htmlCheckAutoClose(name, ctxt->name) == 1) {
        !          4031:                    htmlAutoClose(ctxt, name);
        !          4032:                    continue;
        !          4033:                }
        !          4034:            }
        !          4035:        }
        !          4036: 
        !          4037:        /*
        !          4038:         * Has this node been popped out during parsing of
        !          4039:         * the next element
        !          4040:         */
        !          4041:         if ((ctxt->nameNr > 0) && (depth >= ctxt->nameNr) &&
        !          4042:            (!xmlStrEqual(currentNode, ctxt->name)))
        !          4043:             {
        !          4044:            if (currentNode != NULL) xmlFree(currentNode);
        !          4045:            return;
        !          4046:        }
        !          4047: 
        !          4048:        if ((CUR != 0) && ((xmlStrEqual(currentNode, BAD_CAST"script")) ||
        !          4049:            (xmlStrEqual(currentNode, BAD_CAST"style")))) {
        !          4050:            /*
        !          4051:             * Handle SCRIPT/STYLE separately
        !          4052:             */
        !          4053:            htmlParseScript(ctxt);
        !          4054:        } else {
        !          4055:            /*
        !          4056:             * Sometimes DOCTYPE arrives in the middle of the document
        !          4057:             */
        !          4058:            if ((CUR == '<') && (NXT(1) == '!') &&
        !          4059:                (UPP(2) == 'D') && (UPP(3) == 'O') &&
        !          4060:                (UPP(4) == 'C') && (UPP(5) == 'T') &&
        !          4061:                (UPP(6) == 'Y') && (UPP(7) == 'P') &&
        !          4062:                (UPP(8) == 'E')) {
        !          4063:                htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
        !          4064:                             "Misplaced DOCTYPE declaration\n",
        !          4065:                             BAD_CAST "DOCTYPE" , NULL);
        !          4066:                htmlParseDocTypeDecl(ctxt);
        !          4067:            }
        !          4068: 
        !          4069:            /*
        !          4070:             * First case :  a comment
        !          4071:             */
        !          4072:            if ((CUR == '<') && (NXT(1) == '!') &&
        !          4073:                (NXT(2) == '-') && (NXT(3) == '-')) {
        !          4074:                htmlParseComment(ctxt);
        !          4075:            }
        !          4076: 
        !          4077:            /*
        !          4078:             * Second case : a Processing Instruction.
        !          4079:             */
        !          4080:            else if ((CUR == '<') && (NXT(1) == '?')) {
        !          4081:                htmlParsePI(ctxt);
        !          4082:            }
        !          4083: 
        !          4084:            /*
        !          4085:             * Third case :  a sub-element.
        !          4086:             */
        !          4087:            else if (CUR == '<') {
        !          4088:                htmlParseElement(ctxt);
        !          4089:            }
        !          4090: 
        !          4091:            /*
        !          4092:             * Fourth case : a reference. If if has not been resolved,
        !          4093:             *    parsing returns it's Name, create the node
        !          4094:             */
        !          4095:            else if (CUR == '&') {
        !          4096:                htmlParseReference(ctxt);
        !          4097:            }
        !          4098: 
        !          4099:            /*
        !          4100:             * Fifth case : end of the resource
        !          4101:             */
        !          4102:            else if (CUR == 0) {
        !          4103:                htmlAutoCloseOnEnd(ctxt);
        !          4104:                break;
        !          4105:            }
        !          4106: 
        !          4107:            /*
        !          4108:             * Last case, text. Note that References are handled directly.
        !          4109:             */
        !          4110:            else {
        !          4111:                htmlParseCharData(ctxt);
        !          4112:            }
        !          4113: 
        !          4114:            if (cons == ctxt->nbChars) {
        !          4115:                if (ctxt->node != NULL) {
        !          4116:                    htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          4117:                                 "detected an error in element content\n",
        !          4118:                                 NULL, NULL);
        !          4119:                }
        !          4120:                break;
        !          4121:            }
        !          4122:        }
        !          4123:         GROW;
        !          4124:     }
        !          4125:     if (currentNode != NULL) xmlFree(currentNode);
        !          4126: }
        !          4127: 
        !          4128: /**
        !          4129:  * htmlParseElement:
        !          4130:  * @ctxt:  an HTML parser context
        !          4131:  *
        !          4132:  * parse an HTML element, this is highly recursive
        !          4133:  * this is kept for compatibility with previous code versions
        !          4134:  *
        !          4135:  * [39] element ::= EmptyElemTag | STag content ETag
        !          4136:  *
        !          4137:  * [41] Attribute ::= Name Eq AttValue
        !          4138:  */
        !          4139: 
        !          4140: void
        !          4141: htmlParseElement(htmlParserCtxtPtr ctxt) {
        !          4142:     const xmlChar *name;
        !          4143:     xmlChar *currentNode = NULL;
        !          4144:     const htmlElemDesc * info;
        !          4145:     htmlParserNodeInfo node_info;
        !          4146:     int failed;
        !          4147:     int depth;
        !          4148:     const xmlChar *oldptr;
        !          4149: 
        !          4150:     if ((ctxt == NULL) || (ctxt->input == NULL)) {
        !          4151:        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          4152:                     "htmlParseElement: context error\n", NULL, NULL);
        !          4153:        return;
        !          4154:     }
        !          4155: 
        !          4156:     if (ctxt->instate == XML_PARSER_EOF)
        !          4157:         return;
        !          4158: 
        !          4159:     /* Capture start position */
        !          4160:     if (ctxt->record_info) {
        !          4161:         node_info.begin_pos = ctxt->input->consumed +
        !          4162:                           (CUR_PTR - ctxt->input->base);
        !          4163:        node_info.begin_line = ctxt->input->line;
        !          4164:     }
        !          4165: 
        !          4166:     failed = htmlParseStartTag(ctxt);
        !          4167:     name = ctxt->name;
        !          4168:     if ((failed == -1) || (name == NULL)) {
        !          4169:        if (CUR == '>')
        !          4170:            NEXT;
        !          4171:         return;
        !          4172:     }
        !          4173: 
        !          4174:     /*
        !          4175:      * Lookup the info for that element.
        !          4176:      */
        !          4177:     info = htmlTagLookup(name);
        !          4178:     if (info == NULL) {
        !          4179:        htmlParseErr(ctxt, XML_HTML_UNKNOWN_TAG,
        !          4180:                     "Tag %s invalid\n", name, NULL);
        !          4181:     }
        !          4182: 
        !          4183:     /*
        !          4184:      * Check for an Empty Element labeled the XML/SGML way
        !          4185:      */
        !          4186:     if ((CUR == '/') && (NXT(1) == '>')) {
        !          4187:         SKIP(2);
        !          4188:        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          4189:            ctxt->sax->endElement(ctxt->userData, name);
        !          4190:        htmlnamePop(ctxt);
        !          4191:        return;
        !          4192:     }
        !          4193: 
        !          4194:     if (CUR == '>') {
        !          4195:         NEXT;
        !          4196:     } else {
        !          4197:        htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
        !          4198:                     "Couldn't find end of Start Tag %s\n", name, NULL);
        !          4199: 
        !          4200:        /*
        !          4201:         * end of parsing of this node.
        !          4202:         */
        !          4203:        if (xmlStrEqual(name, ctxt->name)) {
        !          4204:            nodePop(ctxt);
        !          4205:            htmlnamePop(ctxt);
        !          4206:        }
        !          4207: 
        !          4208:        /*
        !          4209:         * Capture end position and add node
        !          4210:         */
        !          4211:        if (ctxt->record_info) {
        !          4212:           node_info.end_pos = ctxt->input->consumed +
        !          4213:                              (CUR_PTR - ctxt->input->base);
        !          4214:           node_info.end_line = ctxt->input->line;
        !          4215:           node_info.node = ctxt->node;
        !          4216:           xmlParserAddNodeInfo(ctxt, &node_info);
        !          4217:        }
        !          4218:        return;
        !          4219:     }
        !          4220: 
        !          4221:     /*
        !          4222:      * Check for an Empty Element from DTD definition
        !          4223:      */
        !          4224:     if ((info != NULL) && (info->empty)) {
        !          4225:        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          4226:            ctxt->sax->endElement(ctxt->userData, name);
        !          4227:        htmlnamePop(ctxt);
        !          4228:        return;
        !          4229:     }
        !          4230: 
        !          4231:     /*
        !          4232:      * Parse the content of the element:
        !          4233:      */
        !          4234:     currentNode = xmlStrdup(ctxt->name);
        !          4235:     depth = ctxt->nameNr;
        !          4236:     while (IS_CHAR_CH(CUR)) {
        !          4237:        oldptr = ctxt->input->cur;
        !          4238:        htmlParseContent(ctxt);
        !          4239:        if (oldptr==ctxt->input->cur) break;
        !          4240:        if (ctxt->nameNr < depth) break;
        !          4241:     }
        !          4242: 
        !          4243:     /*
        !          4244:      * Capture end position and add node
        !          4245:      */
        !          4246:     if ( currentNode != NULL && ctxt->record_info ) {
        !          4247:        node_info.end_pos = ctxt->input->consumed +
        !          4248:                           (CUR_PTR - ctxt->input->base);
        !          4249:        node_info.end_line = ctxt->input->line;
        !          4250:        node_info.node = ctxt->node;
        !          4251:        xmlParserAddNodeInfo(ctxt, &node_info);
        !          4252:     }
        !          4253:     if (!IS_CHAR_CH(CUR)) {
        !          4254:        htmlAutoCloseOnEnd(ctxt);
        !          4255:     }
        !          4256: 
        !          4257:     if (currentNode != NULL)
        !          4258:        xmlFree(currentNode);
        !          4259: }
        !          4260: 
        !          4261: static void
        !          4262: htmlParserFinishElementParsing(htmlParserCtxtPtr ctxt) {
        !          4263:     /*
        !          4264:      * Capture end position and add node
        !          4265:      */
        !          4266:     if ( ctxt->node != NULL && ctxt->record_info ) {
        !          4267:        ctxt->nodeInfo->end_pos = ctxt->input->consumed +
        !          4268:                                 (CUR_PTR - ctxt->input->base);
        !          4269:        ctxt->nodeInfo->end_line = ctxt->input->line;
        !          4270:        ctxt->nodeInfo->node = ctxt->node;
        !          4271:        xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
        !          4272:        htmlNodeInfoPop(ctxt);
        !          4273:     }
        !          4274:     if (!IS_CHAR_CH(CUR)) {
        !          4275:        htmlAutoCloseOnEnd(ctxt);
        !          4276:     }
        !          4277: }
        !          4278: 
        !          4279: /**
        !          4280:  * htmlParseElementInternal:
        !          4281:  * @ctxt:  an HTML parser context
        !          4282:  *
        !          4283:  * parse an HTML element, new version, non recursive
        !          4284:  *
        !          4285:  * [39] element ::= EmptyElemTag | STag content ETag
        !          4286:  *
        !          4287:  * [41] Attribute ::= Name Eq AttValue
        !          4288:  */
        !          4289: 
        !          4290: static void
        !          4291: htmlParseElementInternal(htmlParserCtxtPtr ctxt) {
        !          4292:     const xmlChar *name;
        !          4293:     const htmlElemDesc * info;
        !          4294:     htmlParserNodeInfo node_info;
        !          4295:     int failed;
        !          4296: 
        !          4297:     if ((ctxt == NULL) || (ctxt->input == NULL)) {
        !          4298:        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          4299:                     "htmlParseElementInternal: context error\n", NULL, NULL);
        !          4300:        return;
        !          4301:     }
        !          4302: 
        !          4303:     if (ctxt->instate == XML_PARSER_EOF)
        !          4304:         return;
        !          4305: 
        !          4306:     /* Capture start position */
        !          4307:     if (ctxt->record_info) {
        !          4308:         node_info.begin_pos = ctxt->input->consumed +
        !          4309:                           (CUR_PTR - ctxt->input->base);
        !          4310:        node_info.begin_line = ctxt->input->line;
        !          4311:     }
        !          4312: 
        !          4313:     failed = htmlParseStartTag(ctxt);
        !          4314:     name = ctxt->name;
        !          4315:     if ((failed == -1) || (name == NULL)) {
        !          4316:        if (CUR == '>')
        !          4317:            NEXT;
        !          4318:         return;
        !          4319:     }
        !          4320: 
        !          4321:     /*
        !          4322:      * Lookup the info for that element.
        !          4323:      */
        !          4324:     info = htmlTagLookup(name);
        !          4325:     if (info == NULL) {
        !          4326:        htmlParseErr(ctxt, XML_HTML_UNKNOWN_TAG,
        !          4327:                     "Tag %s invalid\n", name, NULL);
        !          4328:     }
        !          4329: 
        !          4330:     /*
        !          4331:      * Check for an Empty Element labeled the XML/SGML way
        !          4332:      */
        !          4333:     if ((CUR == '/') && (NXT(1) == '>')) {
        !          4334:         SKIP(2);
        !          4335:        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          4336:            ctxt->sax->endElement(ctxt->userData, name);
        !          4337:        htmlnamePop(ctxt);
        !          4338:        return;
        !          4339:     }
        !          4340: 
        !          4341:     if (CUR == '>') {
        !          4342:         NEXT;
        !          4343:     } else {
        !          4344:        htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
        !          4345:                     "Couldn't find end of Start Tag %s\n", name, NULL);
        !          4346: 
        !          4347:        /*
        !          4348:         * end of parsing of this node.
        !          4349:         */
        !          4350:        if (xmlStrEqual(name, ctxt->name)) {
        !          4351:            nodePop(ctxt);
        !          4352:            htmlnamePop(ctxt);
        !          4353:        }
        !          4354: 
        !          4355:         if (ctxt->record_info)
        !          4356:             htmlNodeInfoPush(ctxt, &node_info);
        !          4357:         htmlParserFinishElementParsing(ctxt);
        !          4358:        return;
        !          4359:     }
        !          4360: 
        !          4361:     /*
        !          4362:      * Check for an Empty Element from DTD definition
        !          4363:      */
        !          4364:     if ((info != NULL) && (info->empty)) {
        !          4365:        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          4366:            ctxt->sax->endElement(ctxt->userData, name);
        !          4367:        htmlnamePop(ctxt);
        !          4368:        return;
        !          4369:     }
        !          4370: 
        !          4371:     if (ctxt->record_info)
        !          4372:         htmlNodeInfoPush(ctxt, &node_info);
        !          4373: }
        !          4374: 
        !          4375: /**
        !          4376:  * htmlParseContentInternal:
        !          4377:  * @ctxt:  an HTML parser context
        !          4378:  *
        !          4379:  * Parse a content: comment, sub-element, reference or text.
        !          4380:  * New version for non recursive htmlParseElementInternal
        !          4381:  */
        !          4382: 
        !          4383: static void
        !          4384: htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
        !          4385:     xmlChar *currentNode;
        !          4386:     int depth;
        !          4387:     const xmlChar *name;
        !          4388: 
        !          4389:     currentNode = xmlStrdup(ctxt->name);
        !          4390:     depth = ctxt->nameNr;
        !          4391:     while (1) {
        !          4392:        long cons = ctxt->nbChars;
        !          4393: 
        !          4394:         GROW;
        !          4395: 
        !          4396:         if (ctxt->instate == XML_PARSER_EOF)
        !          4397:             break;
        !          4398: 
        !          4399:        /*
        !          4400:         * Our tag or one of it's parent or children is ending.
        !          4401:         */
        !          4402:         if ((CUR == '<') && (NXT(1) == '/')) {
        !          4403:            if (htmlParseEndTag(ctxt) &&
        !          4404:                ((currentNode != NULL) || (ctxt->nameNr == 0))) {
        !          4405:                if (currentNode != NULL)
        !          4406:                    xmlFree(currentNode);
        !          4407: 
        !          4408:                currentNode = xmlStrdup(ctxt->name);
        !          4409:                depth = ctxt->nameNr;
        !          4410:            }
        !          4411:            continue; /* while */
        !          4412:         }
        !          4413: 
        !          4414:        else if ((CUR == '<') &&
        !          4415:                 ((IS_ASCII_LETTER(NXT(1))) ||
        !          4416:                  (NXT(1) == '_') || (NXT(1) == ':'))) {
        !          4417:            name = htmlParseHTMLName_nonInvasive(ctxt);
        !          4418:            if (name == NULL) {
        !          4419:                htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
        !          4420:                         "htmlParseStartTag: invalid element name\n",
        !          4421:                         NULL, NULL);
        !          4422:                /* Dump the bogus tag like browsers do */
        !          4423:                while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
        !          4424:                    NEXT;
        !          4425: 
        !          4426:                htmlParserFinishElementParsing(ctxt);
        !          4427:                if (currentNode != NULL)
        !          4428:                    xmlFree(currentNode);
        !          4429: 
        !          4430:                currentNode = xmlStrdup(ctxt->name);
        !          4431:                depth = ctxt->nameNr;
        !          4432:                continue;
        !          4433:            }
        !          4434: 
        !          4435:            if (ctxt->name != NULL) {
        !          4436:                if (htmlCheckAutoClose(name, ctxt->name) == 1) {
        !          4437:                    htmlAutoClose(ctxt, name);
        !          4438:                    continue;
        !          4439:                }
        !          4440:            }
        !          4441:        }
        !          4442: 
        !          4443:        /*
        !          4444:         * Has this node been popped out during parsing of
        !          4445:         * the next element
        !          4446:         */
        !          4447:         if ((ctxt->nameNr > 0) && (depth >= ctxt->nameNr) &&
        !          4448:            (!xmlStrEqual(currentNode, ctxt->name)))
        !          4449:             {
        !          4450:            htmlParserFinishElementParsing(ctxt);
        !          4451:            if (currentNode != NULL) xmlFree(currentNode);
        !          4452: 
        !          4453:            currentNode = xmlStrdup(ctxt->name);
        !          4454:            depth = ctxt->nameNr;
        !          4455:            continue;
        !          4456:        }
        !          4457: 
        !          4458:        if ((CUR != 0) && ((xmlStrEqual(currentNode, BAD_CAST"script")) ||
        !          4459:            (xmlStrEqual(currentNode, BAD_CAST"style")))) {
        !          4460:            /*
        !          4461:             * Handle SCRIPT/STYLE separately
        !          4462:             */
        !          4463:            htmlParseScript(ctxt);
        !          4464:        } else {
        !          4465:            /*
        !          4466:             * Sometimes DOCTYPE arrives in the middle of the document
        !          4467:             */
        !          4468:            if ((CUR == '<') && (NXT(1) == '!') &&
        !          4469:                (UPP(2) == 'D') && (UPP(3) == 'O') &&
        !          4470:                (UPP(4) == 'C') && (UPP(5) == 'T') &&
        !          4471:                (UPP(6) == 'Y') && (UPP(7) == 'P') &&
        !          4472:                (UPP(8) == 'E')) {
        !          4473:                htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
        !          4474:                             "Misplaced DOCTYPE declaration\n",
        !          4475:                             BAD_CAST "DOCTYPE" , NULL);
        !          4476:                htmlParseDocTypeDecl(ctxt);
        !          4477:            }
        !          4478: 
        !          4479:            /*
        !          4480:             * First case :  a comment
        !          4481:             */
        !          4482:            if ((CUR == '<') && (NXT(1) == '!') &&
        !          4483:                (NXT(2) == '-') && (NXT(3) == '-')) {
        !          4484:                htmlParseComment(ctxt);
        !          4485:            }
        !          4486: 
        !          4487:            /*
        !          4488:             * Second case : a Processing Instruction.
        !          4489:             */
        !          4490:            else if ((CUR == '<') && (NXT(1) == '?')) {
        !          4491:                htmlParsePI(ctxt);
        !          4492:            }
        !          4493: 
        !          4494:            /*
        !          4495:             * Third case :  a sub-element.
        !          4496:             */
        !          4497:            else if (CUR == '<') {
        !          4498:                htmlParseElementInternal(ctxt);
        !          4499:                if (currentNode != NULL) xmlFree(currentNode);
        !          4500: 
        !          4501:                currentNode = xmlStrdup(ctxt->name);
        !          4502:                depth = ctxt->nameNr;
        !          4503:            }
        !          4504: 
        !          4505:            /*
        !          4506:             * Fourth case : a reference. If if has not been resolved,
        !          4507:             *    parsing returns it's Name, create the node
        !          4508:             */
        !          4509:            else if (CUR == '&') {
        !          4510:                htmlParseReference(ctxt);
        !          4511:            }
        !          4512: 
        !          4513:            /*
        !          4514:             * Fifth case : end of the resource
        !          4515:             */
        !          4516:            else if (CUR == 0) {
        !          4517:                htmlAutoCloseOnEnd(ctxt);
        !          4518:                break;
        !          4519:            }
        !          4520: 
        !          4521:            /*
        !          4522:             * Last case, text. Note that References are handled directly.
        !          4523:             */
        !          4524:            else {
        !          4525:                htmlParseCharData(ctxt);
        !          4526:            }
        !          4527: 
        !          4528:            if (cons == ctxt->nbChars) {
        !          4529:                if (ctxt->node != NULL) {
        !          4530:                    htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          4531:                                 "detected an error in element content\n",
        !          4532:                                 NULL, NULL);
        !          4533:                }
        !          4534:                break;
        !          4535:            }
        !          4536:        }
        !          4537:         GROW;
        !          4538:     }
        !          4539:     if (currentNode != NULL) xmlFree(currentNode);
        !          4540: }
        !          4541: 
        !          4542: /**
        !          4543:  * htmlParseContent:
        !          4544:  * @ctxt:  an HTML parser context
        !          4545:  *
        !          4546:  * Parse a content: comment, sub-element, reference or text.
        !          4547:  * This is the entry point when called from parser.c
        !          4548:  */
        !          4549: 
        !          4550: void
        !          4551: __htmlParseContent(void *ctxt) {
        !          4552:     if (ctxt != NULL)
        !          4553:        htmlParseContentInternal((htmlParserCtxtPtr) ctxt);
        !          4554: }
        !          4555: 
        !          4556: /**
        !          4557:  * htmlParseDocument:
        !          4558:  * @ctxt:  an HTML parser context
        !          4559:  *
        !          4560:  * parse an HTML document (and build a tree if using the standard SAX
        !          4561:  * interface).
        !          4562:  *
        !          4563:  * Returns 0, -1 in case of error. the parser context is augmented
        !          4564:  *                as a result of the parsing.
        !          4565:  */
        !          4566: 
        !          4567: int
        !          4568: htmlParseDocument(htmlParserCtxtPtr ctxt) {
        !          4569:     xmlChar start[4];
        !          4570:     xmlCharEncoding enc;
        !          4571:     xmlDtdPtr dtd;
        !          4572: 
        !          4573:     xmlInitParser();
        !          4574: 
        !          4575:     htmlDefaultSAXHandlerInit();
        !          4576: 
        !          4577:     if ((ctxt == NULL) || (ctxt->input == NULL)) {
        !          4578:        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          4579:                     "htmlParseDocument: context error\n", NULL, NULL);
        !          4580:        return(XML_ERR_INTERNAL_ERROR);
        !          4581:     }
        !          4582:     ctxt->html = 1;
        !          4583:     ctxt->linenumbers = 1;
        !          4584:     GROW;
        !          4585:     /*
        !          4586:      * SAX: beginning of the document processing.
        !          4587:      */
        !          4588:     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
        !          4589:         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
        !          4590: 
        !          4591:     if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) &&
        !          4592:         ((ctxt->input->end - ctxt->input->cur) >= 4)) {
        !          4593:        /*
        !          4594:         * Get the 4 first bytes and decode the charset
        !          4595:         * if enc != XML_CHAR_ENCODING_NONE
        !          4596:         * plug some encoding conversion routines.
        !          4597:         */
        !          4598:        start[0] = RAW;
        !          4599:        start[1] = NXT(1);
        !          4600:        start[2] = NXT(2);
        !          4601:        start[3] = NXT(3);
        !          4602:        enc = xmlDetectCharEncoding(&start[0], 4);
        !          4603:        if (enc != XML_CHAR_ENCODING_NONE) {
        !          4604:            xmlSwitchEncoding(ctxt, enc);
        !          4605:        }
        !          4606:     }
        !          4607: 
        !          4608:     /*
        !          4609:      * Wipe out everything which is before the first '<'
        !          4610:      */
        !          4611:     SKIP_BLANKS;
        !          4612:     if (CUR == 0) {
        !          4613:        htmlParseErr(ctxt, XML_ERR_DOCUMENT_EMPTY,
        !          4614:                     "Document is empty\n", NULL, NULL);
        !          4615:     }
        !          4616: 
        !          4617:     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
        !          4618:        ctxt->sax->startDocument(ctxt->userData);
        !          4619: 
        !          4620: 
        !          4621:     /*
        !          4622:      * Parse possible comments and PIs before any content
        !          4623:      */
        !          4624:     while (((CUR == '<') && (NXT(1) == '!') &&
        !          4625:             (NXT(2) == '-') && (NXT(3) == '-')) ||
        !          4626:           ((CUR == '<') && (NXT(1) == '?'))) {
        !          4627:         htmlParseComment(ctxt);
        !          4628:         htmlParsePI(ctxt);
        !          4629:        SKIP_BLANKS;
        !          4630:     }
        !          4631: 
        !          4632: 
        !          4633:     /*
        !          4634:      * Then possibly doc type declaration(s) and more Misc
        !          4635:      * (doctypedecl Misc*)?
        !          4636:      */
        !          4637:     if ((CUR == '<') && (NXT(1) == '!') &&
        !          4638:        (UPP(2) == 'D') && (UPP(3) == 'O') &&
        !          4639:        (UPP(4) == 'C') && (UPP(5) == 'T') &&
        !          4640:        (UPP(6) == 'Y') && (UPP(7) == 'P') &&
        !          4641:        (UPP(8) == 'E')) {
        !          4642:        htmlParseDocTypeDecl(ctxt);
        !          4643:     }
        !          4644:     SKIP_BLANKS;
        !          4645: 
        !          4646:     /*
        !          4647:      * Parse possible comments and PIs before any content
        !          4648:      */
        !          4649:     while (((CUR == '<') && (NXT(1) == '!') &&
        !          4650:             (NXT(2) == '-') && (NXT(3) == '-')) ||
        !          4651:           ((CUR == '<') && (NXT(1) == '?'))) {
        !          4652:         htmlParseComment(ctxt);
        !          4653:         htmlParsePI(ctxt);
        !          4654:        SKIP_BLANKS;
        !          4655:     }
        !          4656: 
        !          4657:     /*
        !          4658:      * Time to start parsing the tree itself
        !          4659:      */
        !          4660:     htmlParseContentInternal(ctxt);
        !          4661: 
        !          4662:     /*
        !          4663:      * autoclose
        !          4664:      */
        !          4665:     if (CUR == 0)
        !          4666:        htmlAutoCloseOnEnd(ctxt);
        !          4667: 
        !          4668: 
        !          4669:     /*
        !          4670:      * SAX: end of the document processing.
        !          4671:      */
        !          4672:     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
        !          4673:         ctxt->sax->endDocument(ctxt->userData);
        !          4674: 
        !          4675:     if ((!(ctxt->options & HTML_PARSE_NODEFDTD)) && (ctxt->myDoc != NULL)) {
        !          4676:        dtd = xmlGetIntSubset(ctxt->myDoc);
        !          4677:        if (dtd == NULL)
        !          4678:            ctxt->myDoc->intSubset =
        !          4679:                xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html",
        !          4680:                    BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN",
        !          4681:                    BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd");
        !          4682:     }
        !          4683:     if (! ctxt->wellFormed) return(-1);
        !          4684:     return(0);
        !          4685: }
        !          4686: 
        !          4687: 
        !          4688: /************************************************************************
        !          4689:  *                                                                     *
        !          4690:  *                     Parser contexts handling                        *
        !          4691:  *                                                                     *
        !          4692:  ************************************************************************/
        !          4693: 
        !          4694: /**
        !          4695:  * htmlInitParserCtxt:
        !          4696:  * @ctxt:  an HTML parser context
        !          4697:  *
        !          4698:  * Initialize a parser context
        !          4699:  *
        !          4700:  * Returns 0 in case of success and -1 in case of error
        !          4701:  */
        !          4702: 
        !          4703: static int
        !          4704: htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
        !          4705: {
        !          4706:     htmlSAXHandler *sax;
        !          4707: 
        !          4708:     if (ctxt == NULL) return(-1);
        !          4709:     memset(ctxt, 0, sizeof(htmlParserCtxt));
        !          4710: 
        !          4711:     ctxt->dict = xmlDictCreate();
        !          4712:     if (ctxt->dict == NULL) {
        !          4713:         htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
        !          4714:        return(-1);
        !          4715:     }
        !          4716:     sax = (htmlSAXHandler *) xmlMalloc(sizeof(htmlSAXHandler));
        !          4717:     if (sax == NULL) {
        !          4718:         htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
        !          4719:        return(-1);
        !          4720:     }
        !          4721:     else
        !          4722:         memset(sax, 0, sizeof(htmlSAXHandler));
        !          4723: 
        !          4724:     /* Allocate the Input stack */
        !          4725:     ctxt->inputTab = (htmlParserInputPtr *)
        !          4726:                       xmlMalloc(5 * sizeof(htmlParserInputPtr));
        !          4727:     if (ctxt->inputTab == NULL) {
        !          4728:         htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
        !          4729:        ctxt->inputNr = 0;
        !          4730:        ctxt->inputMax = 0;
        !          4731:        ctxt->input = NULL;
        !          4732:        return(-1);
        !          4733:     }
        !          4734:     ctxt->inputNr = 0;
        !          4735:     ctxt->inputMax = 5;
        !          4736:     ctxt->input = NULL;
        !          4737:     ctxt->version = NULL;
        !          4738:     ctxt->encoding = NULL;
        !          4739:     ctxt->standalone = -1;
        !          4740:     ctxt->instate = XML_PARSER_START;
        !          4741: 
        !          4742:     /* Allocate the Node stack */
        !          4743:     ctxt->nodeTab = (htmlNodePtr *) xmlMalloc(10 * sizeof(htmlNodePtr));
        !          4744:     if (ctxt->nodeTab == NULL) {
        !          4745:         htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
        !          4746:        ctxt->nodeNr = 0;
        !          4747:        ctxt->nodeMax = 0;
        !          4748:        ctxt->node = NULL;
        !          4749:        ctxt->inputNr = 0;
        !          4750:        ctxt->inputMax = 0;
        !          4751:        ctxt->input = NULL;
        !          4752:        return(-1);
        !          4753:     }
        !          4754:     ctxt->nodeNr = 0;
        !          4755:     ctxt->nodeMax = 10;
        !          4756:     ctxt->node = NULL;
        !          4757: 
        !          4758:     /* Allocate the Name stack */
        !          4759:     ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
        !          4760:     if (ctxt->nameTab == NULL) {
        !          4761:         htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
        !          4762:        ctxt->nameNr = 0;
        !          4763:        ctxt->nameMax = 0;
        !          4764:        ctxt->name = NULL;
        !          4765:        ctxt->nodeNr = 0;
        !          4766:        ctxt->nodeMax = 0;
        !          4767:        ctxt->node = NULL;
        !          4768:        ctxt->inputNr = 0;
        !          4769:        ctxt->inputMax = 0;
        !          4770:        ctxt->input = NULL;
        !          4771:        return(-1);
        !          4772:     }
        !          4773:     ctxt->nameNr = 0;
        !          4774:     ctxt->nameMax = 10;
        !          4775:     ctxt->name = NULL;
        !          4776: 
        !          4777:     ctxt->nodeInfoTab = NULL;
        !          4778:     ctxt->nodeInfoNr  = 0;
        !          4779:     ctxt->nodeInfoMax = 0;
        !          4780: 
        !          4781:     if (sax == NULL) ctxt->sax = (xmlSAXHandlerPtr) &htmlDefaultSAXHandler;
        !          4782:     else {
        !          4783:         ctxt->sax = sax;
        !          4784:        memcpy(sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1));
        !          4785:     }
        !          4786:     ctxt->userData = ctxt;
        !          4787:     ctxt->myDoc = NULL;
        !          4788:     ctxt->wellFormed = 1;
        !          4789:     ctxt->replaceEntities = 0;
        !          4790:     ctxt->linenumbers = xmlLineNumbersDefaultValue;
        !          4791:     ctxt->html = 1;
        !          4792:     ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_0;
        !          4793:     ctxt->vctxt.userData = ctxt;
        !          4794:     ctxt->vctxt.error = xmlParserValidityError;
        !          4795:     ctxt->vctxt.warning = xmlParserValidityWarning;
        !          4796:     ctxt->record_info = 0;
        !          4797:     ctxt->validate = 0;
        !          4798:     ctxt->nbChars = 0;
        !          4799:     ctxt->checkIndex = 0;
        !          4800:     ctxt->catalogs = NULL;
        !          4801:     xmlInitNodeInfoSeq(&ctxt->node_seq);
        !          4802:     return(0);
        !          4803: }
        !          4804: 
        !          4805: /**
        !          4806:  * htmlFreeParserCtxt:
        !          4807:  * @ctxt:  an HTML parser context
        !          4808:  *
        !          4809:  * Free all the memory used by a parser context. However the parsed
        !          4810:  * document in ctxt->myDoc is not freed.
        !          4811:  */
        !          4812: 
        !          4813: void
        !          4814: htmlFreeParserCtxt(htmlParserCtxtPtr ctxt)
        !          4815: {
        !          4816:     xmlFreeParserCtxt(ctxt);
        !          4817: }
        !          4818: 
        !          4819: /**
        !          4820:  * htmlNewParserCtxt:
        !          4821:  *
        !          4822:  * Allocate and initialize a new parser context.
        !          4823:  *
        !          4824:  * Returns the htmlParserCtxtPtr or NULL in case of allocation error
        !          4825:  */
        !          4826: 
        !          4827: htmlParserCtxtPtr
        !          4828: htmlNewParserCtxt(void)
        !          4829: {
        !          4830:     xmlParserCtxtPtr ctxt;
        !          4831: 
        !          4832:     ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
        !          4833:     if (ctxt == NULL) {
        !          4834:         htmlErrMemory(NULL, "NewParserCtxt: out of memory\n");
        !          4835:        return(NULL);
        !          4836:     }
        !          4837:     memset(ctxt, 0, sizeof(xmlParserCtxt));
        !          4838:     if (htmlInitParserCtxt(ctxt) < 0) {
        !          4839:         htmlFreeParserCtxt(ctxt);
        !          4840:        return(NULL);
        !          4841:     }
        !          4842:     return(ctxt);
        !          4843: }
        !          4844: 
        !          4845: /**
        !          4846:  * htmlCreateMemoryParserCtxt:
        !          4847:  * @buffer:  a pointer to a char array
        !          4848:  * @size:  the size of the array
        !          4849:  *
        !          4850:  * Create a parser context for an HTML in-memory document.
        !          4851:  *
        !          4852:  * Returns the new parser context or NULL
        !          4853:  */
        !          4854: htmlParserCtxtPtr
        !          4855: htmlCreateMemoryParserCtxt(const char *buffer, int size) {
        !          4856:     xmlParserCtxtPtr ctxt;
        !          4857:     xmlParserInputPtr input;
        !          4858:     xmlParserInputBufferPtr buf;
        !          4859: 
        !          4860:     if (buffer == NULL)
        !          4861:        return(NULL);
        !          4862:     if (size <= 0)
        !          4863:        return(NULL);
        !          4864: 
        !          4865:     ctxt = htmlNewParserCtxt();
        !          4866:     if (ctxt == NULL)
        !          4867:        return(NULL);
        !          4868: 
        !          4869:     buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
        !          4870:     if (buf == NULL) return(NULL);
        !          4871: 
        !          4872:     input = xmlNewInputStream(ctxt);
        !          4873:     if (input == NULL) {
        !          4874:        xmlFreeParserCtxt(ctxt);
        !          4875:        return(NULL);
        !          4876:     }
        !          4877: 
        !          4878:     input->filename = NULL;
        !          4879:     input->buf = buf;
        !          4880:     input->base = input->buf->buffer->content;
        !          4881:     input->cur = input->buf->buffer->content;
        !          4882:     input->end = &input->buf->buffer->content[input->buf->buffer->use];
        !          4883: 
        !          4884:     inputPush(ctxt, input);
        !          4885:     return(ctxt);
        !          4886: }
        !          4887: 
        !          4888: /**
        !          4889:  * htmlCreateDocParserCtxt:
        !          4890:  * @cur:  a pointer to an array of xmlChar
        !          4891:  * @encoding:  a free form C string describing the HTML document encoding, or NULL
        !          4892:  *
        !          4893:  * Create a parser context for an HTML document.
        !          4894:  *
        !          4895:  * TODO: check the need to add encoding handling there
        !          4896:  *
        !          4897:  * Returns the new parser context or NULL
        !          4898:  */
        !          4899: static htmlParserCtxtPtr
        !          4900: htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
        !          4901:     int len;
        !          4902:     htmlParserCtxtPtr ctxt;
        !          4903: 
        !          4904:     if (cur == NULL)
        !          4905:        return(NULL);
        !          4906:     len = xmlStrlen(cur);
        !          4907:     ctxt = htmlCreateMemoryParserCtxt((char *)cur, len);
        !          4908:     if (ctxt == NULL)
        !          4909:        return(NULL);
        !          4910: 
        !          4911:     if (encoding != NULL) {
        !          4912:        xmlCharEncoding enc;
        !          4913:        xmlCharEncodingHandlerPtr handler;
        !          4914: 
        !          4915:        if (ctxt->input->encoding != NULL)
        !          4916:            xmlFree((xmlChar *) ctxt->input->encoding);
        !          4917:        ctxt->input->encoding = xmlStrdup((const xmlChar *) encoding);
        !          4918: 
        !          4919:        enc = xmlParseCharEncoding(encoding);
        !          4920:        /*
        !          4921:         * registered set of known encodings
        !          4922:         */
        !          4923:        if (enc != XML_CHAR_ENCODING_ERROR) {
        !          4924:            xmlSwitchEncoding(ctxt, enc);
        !          4925:            if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
        !          4926:                htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
        !          4927:                             "Unsupported encoding %s\n",
        !          4928:                             (const xmlChar *) encoding, NULL);
        !          4929:            }
        !          4930:        } else {
        !          4931:            /*
        !          4932:             * fallback for unknown encodings
        !          4933:             */
        !          4934:            handler = xmlFindCharEncodingHandler((const char *) encoding);
        !          4935:            if (handler != NULL) {
        !          4936:                xmlSwitchToEncoding(ctxt, handler);
        !          4937:            } else {
        !          4938:                htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
        !          4939:                             "Unsupported encoding %s\n",
        !          4940:                             (const xmlChar *) encoding, NULL);
        !          4941:            }
        !          4942:        }
        !          4943:     }
        !          4944:     return(ctxt);
        !          4945: }
        !          4946: 
        !          4947: #ifdef LIBXML_PUSH_ENABLED
        !          4948: /************************************************************************
        !          4949:  *                                                                     *
        !          4950:  *     Progressive parsing interfaces                          *
        !          4951:  *                                                                     *
        !          4952:  ************************************************************************/
        !          4953: 
        !          4954: /**
        !          4955:  * htmlParseLookupSequence:
        !          4956:  * @ctxt:  an HTML parser context
        !          4957:  * @first:  the first char to lookup
        !          4958:  * @next:  the next char to lookup or zero
        !          4959:  * @third:  the next char to lookup or zero
        !          4960:  * @comment: flag to force checking inside comments
        !          4961:  *
        !          4962:  * Try to find if a sequence (first, next, third) or  just (first next) or
        !          4963:  * (first) is available in the input stream.
        !          4964:  * This function has a side effect of (possibly) incrementing ctxt->checkIndex
        !          4965:  * to avoid rescanning sequences of bytes, it DOES change the state of the
        !          4966:  * parser, do not use liberally.
        !          4967:  * This is basically similar to xmlParseLookupSequence()
        !          4968:  *
        !          4969:  * Returns the index to the current parsing point if the full sequence
        !          4970:  *      is available, -1 otherwise.
        !          4971:  */
        !          4972: static int
        !          4973: htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
        !          4974:                         xmlChar next, xmlChar third, int iscomment,
        !          4975:                         int ignoreattrval)
        !          4976: {
        !          4977:     int base, len;
        !          4978:     htmlParserInputPtr in;
        !          4979:     const xmlChar *buf;
        !          4980:     int incomment = 0;
        !          4981:     int invalue = 0;
        !          4982:     char valdellim = 0x0;
        !          4983: 
        !          4984:     in = ctxt->input;
        !          4985:     if (in == NULL)
        !          4986:         return (-1);
        !          4987: 
        !          4988:     base = in->cur - in->base;
        !          4989:     if (base < 0)
        !          4990:         return (-1);
        !          4991: 
        !          4992:     if (ctxt->checkIndex > base)
        !          4993:         base = ctxt->checkIndex;
        !          4994: 
        !          4995:     if (in->buf == NULL) {
        !          4996:         buf = in->base;
        !          4997:         len = in->length;
        !          4998:     } else {
        !          4999:         buf = in->buf->buffer->content;
        !          5000:         len = in->buf->buffer->use;
        !          5001:     }
        !          5002: 
        !          5003:     /* take into account the sequence length */
        !          5004:     if (third)
        !          5005:         len -= 2;
        !          5006:     else if (next)
        !          5007:         len--;
        !          5008:     for (; base < len; base++) {
        !          5009:         if ((!incomment) && (base + 4 < len) && (!iscomment)) {
        !          5010:             if ((buf[base] == '<') && (buf[base + 1] == '!') &&
        !          5011:                 (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
        !          5012:                 incomment = 1;
        !          5013:                 /* do not increment past <! - some people use <!--> */
        !          5014:                 base += 2;
        !          5015:             }
        !          5016:         }
        !          5017:         if (ignoreattrval) {
        !          5018:             if (buf[base] == '"' || buf[base] == '\'') {
        !          5019:                 if (invalue) {
        !          5020:                     if (buf[base] == valdellim) {
        !          5021:                         invalue = 0;
        !          5022:                         continue;
        !          5023:                     }
        !          5024:                 } else {
        !          5025:                     valdellim = buf[base];
        !          5026:                     invalue = 1;
        !          5027:                     continue;
        !          5028:                 }
        !          5029:             } else if (invalue) {
        !          5030:                 continue;
        !          5031:             }
        !          5032:         }
        !          5033:         if (incomment) {
        !          5034:             if (base + 3 > len)
        !          5035:                 return (-1);
        !          5036:             if ((buf[base] == '-') && (buf[base + 1] == '-') &&
        !          5037:                 (buf[base + 2] == '>')) {
        !          5038:                 incomment = 0;
        !          5039:                 base += 2;
        !          5040:             }
        !          5041:             continue;
        !          5042:         }
        !          5043:         if (buf[base] == first) {
        !          5044:             if (third != 0) {
        !          5045:                 if ((buf[base + 1] != next) || (buf[base + 2] != third))
        !          5046:                     continue;
        !          5047:             } else if (next != 0) {
        !          5048:                 if (buf[base + 1] != next)
        !          5049:                     continue;
        !          5050:             }
        !          5051:             ctxt->checkIndex = 0;
        !          5052: #ifdef DEBUG_PUSH
        !          5053:             if (next == 0)
        !          5054:                 xmlGenericError(xmlGenericErrorContext,
        !          5055:                                 "HPP: lookup '%c' found at %d\n",
        !          5056:                                 first, base);
        !          5057:             else if (third == 0)
        !          5058:                 xmlGenericError(xmlGenericErrorContext,
        !          5059:                                 "HPP: lookup '%c%c' found at %d\n",
        !          5060:                                 first, next, base);
        !          5061:             else
        !          5062:                 xmlGenericError(xmlGenericErrorContext,
        !          5063:                                 "HPP: lookup '%c%c%c' found at %d\n",
        !          5064:                                 first, next, third, base);
        !          5065: #endif
        !          5066:             return (base - (in->cur - in->base));
        !          5067:         }
        !          5068:     }
        !          5069:     if ((!incomment) && (!invalue))
        !          5070:         ctxt->checkIndex = base;
        !          5071: #ifdef DEBUG_PUSH
        !          5072:     if (next == 0)
        !          5073:         xmlGenericError(xmlGenericErrorContext,
        !          5074:                         "HPP: lookup '%c' failed\n", first);
        !          5075:     else if (third == 0)
        !          5076:         xmlGenericError(xmlGenericErrorContext,
        !          5077:                         "HPP: lookup '%c%c' failed\n", first, next);
        !          5078:     else
        !          5079:         xmlGenericError(xmlGenericErrorContext,
        !          5080:                         "HPP: lookup '%c%c%c' failed\n", first, next,
        !          5081:                         third);
        !          5082: #endif
        !          5083:     return (-1);
        !          5084: }
        !          5085: 
        !          5086: /**
        !          5087:  * htmlParseLookupChars:
        !          5088:  * @ctxt: an HTML parser context
        !          5089:  * @stop: Array of chars, which stop the lookup.
        !          5090:  * @stopLen: Length of stop-Array
        !          5091:  *
        !          5092:  * Try to find if any char of the stop-Array is available in the input 
        !          5093:  * stream.
        !          5094:  * This function has a side effect of (possibly) incrementing ctxt->checkIndex
        !          5095:  * to avoid rescanning sequences of bytes, it DOES change the state of the
        !          5096:  * parser, do not use liberally.
        !          5097:  *
        !          5098:  * Returns the index to the current parsing point if a stopChar 
        !          5099:  *      is available, -1 otherwise.
        !          5100:  */
        !          5101: static int
        !          5102: htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
        !          5103:                      int stopLen)
        !          5104: {
        !          5105:     int base, len;
        !          5106:     htmlParserInputPtr in;
        !          5107:     const xmlChar *buf;
        !          5108:     int incomment = 0;
        !          5109:     int i;
        !          5110: 
        !          5111:     in = ctxt->input;
        !          5112:     if (in == NULL)
        !          5113:         return (-1);
        !          5114: 
        !          5115:     base = in->cur - in->base;
        !          5116:     if (base < 0)
        !          5117:         return (-1);
        !          5118: 
        !          5119:     if (ctxt->checkIndex > base)
        !          5120:         base = ctxt->checkIndex;
        !          5121: 
        !          5122:     if (in->buf == NULL) {
        !          5123:         buf = in->base;
        !          5124:         len = in->length;
        !          5125:     } else {
        !          5126:         buf = in->buf->buffer->content;
        !          5127:         len = in->buf->buffer->use;
        !          5128:     }
        !          5129: 
        !          5130:     for (; base < len; base++) {
        !          5131:         if (!incomment && (base + 4 < len)) {
        !          5132:             if ((buf[base] == '<') && (buf[base + 1] == '!') &&
        !          5133:                 (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
        !          5134:                 incomment = 1;
        !          5135:                 /* do not increment past <! - some people use <!--> */
        !          5136:                 base += 2;
        !          5137:             }
        !          5138:         }
        !          5139:         if (incomment) {
        !          5140:             if (base + 3 > len)
        !          5141:                 return (-1);
        !          5142:             if ((buf[base] == '-') && (buf[base + 1] == '-') &&
        !          5143:                 (buf[base + 2] == '>')) {
        !          5144:                 incomment = 0;
        !          5145:                 base += 2;
        !          5146:             }
        !          5147:             continue;
        !          5148:         }
        !          5149:         for (i = 0; i < stopLen; ++i) {
        !          5150:             if (buf[base] == stop[i]) {
        !          5151:                 ctxt->checkIndex = 0;
        !          5152:                 return (base - (in->cur - in->base));
        !          5153:             }
        !          5154:         }
        !          5155:     }
        !          5156:     ctxt->checkIndex = base;
        !          5157:     return (-1);
        !          5158: }
        !          5159: 
        !          5160: /**
        !          5161:  * htmlParseTryOrFinish:
        !          5162:  * @ctxt:  an HTML parser context
        !          5163:  * @terminate:  last chunk indicator
        !          5164:  *
        !          5165:  * Try to progress on parsing
        !          5166:  *
        !          5167:  * Returns zero if no parsing was possible
        !          5168:  */
        !          5169: static int
        !          5170: htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
        !          5171:     int ret = 0;
        !          5172:     htmlParserInputPtr in;
        !          5173:     int avail = 0;
        !          5174:     xmlChar cur, next;
        !          5175: 
        !          5176: #ifdef DEBUG_PUSH
        !          5177:     switch (ctxt->instate) {
        !          5178:        case XML_PARSER_EOF:
        !          5179:            xmlGenericError(xmlGenericErrorContext,
        !          5180:                    "HPP: try EOF\n"); break;
        !          5181:        case XML_PARSER_START:
        !          5182:            xmlGenericError(xmlGenericErrorContext,
        !          5183:                    "HPP: try START\n"); break;
        !          5184:        case XML_PARSER_MISC:
        !          5185:            xmlGenericError(xmlGenericErrorContext,
        !          5186:                    "HPP: try MISC\n");break;
        !          5187:        case XML_PARSER_COMMENT:
        !          5188:            xmlGenericError(xmlGenericErrorContext,
        !          5189:                    "HPP: try COMMENT\n");break;
        !          5190:        case XML_PARSER_PROLOG:
        !          5191:            xmlGenericError(xmlGenericErrorContext,
        !          5192:                    "HPP: try PROLOG\n");break;
        !          5193:        case XML_PARSER_START_TAG:
        !          5194:            xmlGenericError(xmlGenericErrorContext,
        !          5195:                    "HPP: try START_TAG\n");break;
        !          5196:        case XML_PARSER_CONTENT:
        !          5197:            xmlGenericError(xmlGenericErrorContext,
        !          5198:                    "HPP: try CONTENT\n");break;
        !          5199:        case XML_PARSER_CDATA_SECTION:
        !          5200:            xmlGenericError(xmlGenericErrorContext,
        !          5201:                    "HPP: try CDATA_SECTION\n");break;
        !          5202:        case XML_PARSER_END_TAG:
        !          5203:            xmlGenericError(xmlGenericErrorContext,
        !          5204:                    "HPP: try END_TAG\n");break;
        !          5205:        case XML_PARSER_ENTITY_DECL:
        !          5206:            xmlGenericError(xmlGenericErrorContext,
        !          5207:                    "HPP: try ENTITY_DECL\n");break;
        !          5208:        case XML_PARSER_ENTITY_VALUE:
        !          5209:            xmlGenericError(xmlGenericErrorContext,
        !          5210:                    "HPP: try ENTITY_VALUE\n");break;
        !          5211:        case XML_PARSER_ATTRIBUTE_VALUE:
        !          5212:            xmlGenericError(xmlGenericErrorContext,
        !          5213:                    "HPP: try ATTRIBUTE_VALUE\n");break;
        !          5214:        case XML_PARSER_DTD:
        !          5215:            xmlGenericError(xmlGenericErrorContext,
        !          5216:                    "HPP: try DTD\n");break;
        !          5217:        case XML_PARSER_EPILOG:
        !          5218:            xmlGenericError(xmlGenericErrorContext,
        !          5219:                    "HPP: try EPILOG\n");break;
        !          5220:        case XML_PARSER_PI:
        !          5221:            xmlGenericError(xmlGenericErrorContext,
        !          5222:                    "HPP: try PI\n");break;
        !          5223:        case XML_PARSER_SYSTEM_LITERAL:
        !          5224:            xmlGenericError(xmlGenericErrorContext,
        !          5225:                    "HPP: try SYSTEM_LITERAL\n");break;
        !          5226:     }
        !          5227: #endif
        !          5228: 
        !          5229:     while (1) {
        !          5230: 
        !          5231:        in = ctxt->input;
        !          5232:        if (in == NULL) break;
        !          5233:        if (in->buf == NULL)
        !          5234:            avail = in->length - (in->cur - in->base);
        !          5235:        else
        !          5236:            avail = in->buf->buffer->use - (in->cur - in->base);
        !          5237:        if ((avail == 0) && (terminate)) {
        !          5238:            htmlAutoCloseOnEnd(ctxt);
        !          5239:            if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) {
        !          5240:                /*
        !          5241:                 * SAX: end of the document processing.
        !          5242:                 */
        !          5243:                ctxt->instate = XML_PARSER_EOF;
        !          5244:                if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
        !          5245:                    ctxt->sax->endDocument(ctxt->userData);
        !          5246:            }
        !          5247:        }
        !          5248:         if (avail < 1)
        !          5249:            goto done;
        !          5250:        cur = in->cur[0];
        !          5251:        if (cur == 0) {
        !          5252:            SKIP(1);
        !          5253:            continue;
        !          5254:        }
        !          5255: 
        !          5256:         switch (ctxt->instate) {
        !          5257:             case XML_PARSER_EOF:
        !          5258:                /*
        !          5259:                 * Document parsing is done !
        !          5260:                 */
        !          5261:                goto done;
        !          5262:             case XML_PARSER_START:
        !          5263:                /*
        !          5264:                 * Very first chars read from the document flow.
        !          5265:                 */
        !          5266:                cur = in->cur[0];
        !          5267:                if (IS_BLANK_CH(cur)) {
        !          5268:                    SKIP_BLANKS;
        !          5269:                    if (in->buf == NULL)
        !          5270:                        avail = in->length - (in->cur - in->base);
        !          5271:                    else
        !          5272:                        avail = in->buf->buffer->use - (in->cur - in->base);
        !          5273:                }
        !          5274:                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
        !          5275:                    ctxt->sax->setDocumentLocator(ctxt->userData,
        !          5276:                                                  &xmlDefaultSAXLocator);
        !          5277:                if ((ctxt->sax) && (ctxt->sax->startDocument) &&
        !          5278:                    (!ctxt->disableSAX))
        !          5279:                    ctxt->sax->startDocument(ctxt->userData);
        !          5280: 
        !          5281:                cur = in->cur[0];
        !          5282:                next = in->cur[1];
        !          5283:                if ((cur == '<') && (next == '!') &&
        !          5284:                    (UPP(2) == 'D') && (UPP(3) == 'O') &&
        !          5285:                    (UPP(4) == 'C') && (UPP(5) == 'T') &&
        !          5286:                    (UPP(6) == 'Y') && (UPP(7) == 'P') &&
        !          5287:                    (UPP(8) == 'E')) {
        !          5288:                    if ((!terminate) &&
        !          5289:                        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5290:                        goto done;
        !          5291: #ifdef DEBUG_PUSH
        !          5292:                    xmlGenericError(xmlGenericErrorContext,
        !          5293:                            "HPP: Parsing internal subset\n");
        !          5294: #endif
        !          5295:                    htmlParseDocTypeDecl(ctxt);
        !          5296:                    ctxt->instate = XML_PARSER_PROLOG;
        !          5297: #ifdef DEBUG_PUSH
        !          5298:                    xmlGenericError(xmlGenericErrorContext,
        !          5299:                            "HPP: entering PROLOG\n");
        !          5300: #endif
        !          5301:                 } else {
        !          5302:                    ctxt->instate = XML_PARSER_MISC;
        !          5303: #ifdef DEBUG_PUSH
        !          5304:                    xmlGenericError(xmlGenericErrorContext,
        !          5305:                            "HPP: entering MISC\n");
        !          5306: #endif
        !          5307:                }
        !          5308:                break;
        !          5309:             case XML_PARSER_MISC:
        !          5310:                SKIP_BLANKS;
        !          5311:                if (in->buf == NULL)
        !          5312:                    avail = in->length - (in->cur - in->base);
        !          5313:                else
        !          5314:                    avail = in->buf->buffer->use - (in->cur - in->base);
        !          5315:                if (avail < 2)
        !          5316:                    goto done;
        !          5317:                cur = in->cur[0];
        !          5318:                next = in->cur[1];
        !          5319:                if ((cur == '<') && (next == '!') &&
        !          5320:                    (in->cur[2] == '-') && (in->cur[3] == '-')) {
        !          5321:                    if ((!terminate) &&
        !          5322:                        (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
        !          5323:                        goto done;
        !          5324: #ifdef DEBUG_PUSH
        !          5325:                    xmlGenericError(xmlGenericErrorContext,
        !          5326:                            "HPP: Parsing Comment\n");
        !          5327: #endif
        !          5328:                    htmlParseComment(ctxt);
        !          5329:                    ctxt->instate = XML_PARSER_MISC;
        !          5330:                } else if ((cur == '<') && (next == '?')) {
        !          5331:                    if ((!terminate) &&
        !          5332:                        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5333:                        goto done;
        !          5334: #ifdef DEBUG_PUSH
        !          5335:                    xmlGenericError(xmlGenericErrorContext,
        !          5336:                            "HPP: Parsing PI\n");
        !          5337: #endif
        !          5338:                    htmlParsePI(ctxt);
        !          5339:                    ctxt->instate = XML_PARSER_MISC;
        !          5340:                } else if ((cur == '<') && (next == '!') &&
        !          5341:                    (UPP(2) == 'D') && (UPP(3) == 'O') &&
        !          5342:                    (UPP(4) == 'C') && (UPP(5) == 'T') &&
        !          5343:                    (UPP(6) == 'Y') && (UPP(7) == 'P') &&
        !          5344:                    (UPP(8) == 'E')) {
        !          5345:                    if ((!terminate) &&
        !          5346:                        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5347:                        goto done;
        !          5348: #ifdef DEBUG_PUSH
        !          5349:                    xmlGenericError(xmlGenericErrorContext,
        !          5350:                            "HPP: Parsing internal subset\n");
        !          5351: #endif
        !          5352:                    htmlParseDocTypeDecl(ctxt);
        !          5353:                    ctxt->instate = XML_PARSER_PROLOG;
        !          5354: #ifdef DEBUG_PUSH
        !          5355:                    xmlGenericError(xmlGenericErrorContext,
        !          5356:                            "HPP: entering PROLOG\n");
        !          5357: #endif
        !          5358:                } else if ((cur == '<') && (next == '!') &&
        !          5359:                           (avail < 9)) {
        !          5360:                    goto done;
        !          5361:                } else {
        !          5362:                    ctxt->instate = XML_PARSER_START_TAG;
        !          5363: #ifdef DEBUG_PUSH
        !          5364:                    xmlGenericError(xmlGenericErrorContext,
        !          5365:                            "HPP: entering START_TAG\n");
        !          5366: #endif
        !          5367:                }
        !          5368:                break;
        !          5369:             case XML_PARSER_PROLOG:
        !          5370:                SKIP_BLANKS;
        !          5371:                if (in->buf == NULL)
        !          5372:                    avail = in->length - (in->cur - in->base);
        !          5373:                else
        !          5374:                    avail = in->buf->buffer->use - (in->cur - in->base);
        !          5375:                if (avail < 2)
        !          5376:                    goto done;
        !          5377:                cur = in->cur[0];
        !          5378:                next = in->cur[1];
        !          5379:                if ((cur == '<') && (next == '!') &&
        !          5380:                    (in->cur[2] == '-') && (in->cur[3] == '-')) {
        !          5381:                    if ((!terminate) &&
        !          5382:                        (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
        !          5383:                        goto done;
        !          5384: #ifdef DEBUG_PUSH
        !          5385:                    xmlGenericError(xmlGenericErrorContext,
        !          5386:                            "HPP: Parsing Comment\n");
        !          5387: #endif
        !          5388:                    htmlParseComment(ctxt);
        !          5389:                    ctxt->instate = XML_PARSER_PROLOG;
        !          5390:                } else if ((cur == '<') && (next == '?')) {
        !          5391:                    if ((!terminate) &&
        !          5392:                        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5393:                        goto done;
        !          5394: #ifdef DEBUG_PUSH
        !          5395:                    xmlGenericError(xmlGenericErrorContext,
        !          5396:                            "HPP: Parsing PI\n");
        !          5397: #endif
        !          5398:                    htmlParsePI(ctxt);
        !          5399:                    ctxt->instate = XML_PARSER_PROLOG;
        !          5400:                } else if ((cur == '<') && (next == '!') &&
        !          5401:                           (avail < 4)) {
        !          5402:                    goto done;
        !          5403:                } else {
        !          5404:                    ctxt->instate = XML_PARSER_START_TAG;
        !          5405: #ifdef DEBUG_PUSH
        !          5406:                    xmlGenericError(xmlGenericErrorContext,
        !          5407:                            "HPP: entering START_TAG\n");
        !          5408: #endif
        !          5409:                }
        !          5410:                break;
        !          5411:             case XML_PARSER_EPILOG:
        !          5412:                if (in->buf == NULL)
        !          5413:                    avail = in->length - (in->cur - in->base);
        !          5414:                else
        !          5415:                    avail = in->buf->buffer->use - (in->cur - in->base);
        !          5416:                if (avail < 1)
        !          5417:                    goto done;
        !          5418:                cur = in->cur[0];
        !          5419:                if (IS_BLANK_CH(cur)) {
        !          5420:                    htmlParseCharData(ctxt);
        !          5421:                    goto done;
        !          5422:                }
        !          5423:                if (avail < 2)
        !          5424:                    goto done;
        !          5425:                next = in->cur[1];
        !          5426:                if ((cur == '<') && (next == '!') &&
        !          5427:                    (in->cur[2] == '-') && (in->cur[3] == '-')) {
        !          5428:                    if ((!terminate) &&
        !          5429:                        (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
        !          5430:                        goto done;
        !          5431: #ifdef DEBUG_PUSH
        !          5432:                    xmlGenericError(xmlGenericErrorContext,
        !          5433:                            "HPP: Parsing Comment\n");
        !          5434: #endif
        !          5435:                    htmlParseComment(ctxt);
        !          5436:                    ctxt->instate = XML_PARSER_EPILOG;
        !          5437:                } else if ((cur == '<') && (next == '?')) {
        !          5438:                    if ((!terminate) &&
        !          5439:                        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5440:                        goto done;
        !          5441: #ifdef DEBUG_PUSH
        !          5442:                    xmlGenericError(xmlGenericErrorContext,
        !          5443:                            "HPP: Parsing PI\n");
        !          5444: #endif
        !          5445:                    htmlParsePI(ctxt);
        !          5446:                    ctxt->instate = XML_PARSER_EPILOG;
        !          5447:                } else if ((cur == '<') && (next == '!') &&
        !          5448:                           (avail < 4)) {
        !          5449:                    goto done;
        !          5450:                } else {
        !          5451:                    ctxt->errNo = XML_ERR_DOCUMENT_END;
        !          5452:                    ctxt->wellFormed = 0;
        !          5453:                    ctxt->instate = XML_PARSER_EOF;
        !          5454: #ifdef DEBUG_PUSH
        !          5455:                    xmlGenericError(xmlGenericErrorContext,
        !          5456:                            "HPP: entering EOF\n");
        !          5457: #endif
        !          5458:                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
        !          5459:                        ctxt->sax->endDocument(ctxt->userData);
        !          5460:                    goto done;
        !          5461:                }
        !          5462:                break;
        !          5463:             case XML_PARSER_START_TAG: {
        !          5464:                const xmlChar *name;
        !          5465:                int failed;
        !          5466:                const htmlElemDesc * info;
        !          5467: 
        !          5468:                if (avail < 2)
        !          5469:                    goto done;
        !          5470:                cur = in->cur[0];
        !          5471:                if (cur != '<') {
        !          5472:                    ctxt->instate = XML_PARSER_CONTENT;
        !          5473: #ifdef DEBUG_PUSH
        !          5474:                    xmlGenericError(xmlGenericErrorContext,
        !          5475:                            "HPP: entering CONTENT\n");
        !          5476: #endif
        !          5477:                    break;
        !          5478:                }
        !          5479:                if (in->cur[1] == '/') {
        !          5480:                    ctxt->instate = XML_PARSER_END_TAG;
        !          5481:                    ctxt->checkIndex = 0;
        !          5482: #ifdef DEBUG_PUSH
        !          5483:                    xmlGenericError(xmlGenericErrorContext,
        !          5484:                            "HPP: entering END_TAG\n");
        !          5485: #endif
        !          5486:                    break;
        !          5487:                }
        !          5488:                if ((!terminate) &&
        !          5489:                    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5490:                    goto done;
        !          5491: 
        !          5492:                failed = htmlParseStartTag(ctxt);
        !          5493:                name = ctxt->name;
        !          5494:                if ((failed == -1) ||
        !          5495:                    (name == NULL)) {
        !          5496:                    if (CUR == '>')
        !          5497:                        NEXT;
        !          5498:                    break;
        !          5499:                }
        !          5500: 
        !          5501:                /*
        !          5502:                 * Lookup the info for that element.
        !          5503:                 */
        !          5504:                info = htmlTagLookup(name);
        !          5505:                if (info == NULL) {
        !          5506:                    htmlParseErr(ctxt, XML_HTML_UNKNOWN_TAG,
        !          5507:                                 "Tag %s invalid\n", name, NULL);
        !          5508:                }
        !          5509: 
        !          5510:                /*
        !          5511:                 * Check for an Empty Element labeled the XML/SGML way
        !          5512:                 */
        !          5513:                if ((CUR == '/') && (NXT(1) == '>')) {
        !          5514:                    SKIP(2);
        !          5515:                    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          5516:                        ctxt->sax->endElement(ctxt->userData, name);
        !          5517:                    htmlnamePop(ctxt);
        !          5518:                    ctxt->instate = XML_PARSER_CONTENT;
        !          5519: #ifdef DEBUG_PUSH
        !          5520:                    xmlGenericError(xmlGenericErrorContext,
        !          5521:                            "HPP: entering CONTENT\n");
        !          5522: #endif
        !          5523:                    break;
        !          5524:                }
        !          5525: 
        !          5526:                if (CUR == '>') {
        !          5527:                    NEXT;
        !          5528:                } else {
        !          5529:                    htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
        !          5530:                                 "Couldn't find end of Start Tag %s\n",
        !          5531:                                 name, NULL);
        !          5532: 
        !          5533:                    /*
        !          5534:                     * end of parsing of this node.
        !          5535:                     */
        !          5536:                    if (xmlStrEqual(name, ctxt->name)) {
        !          5537:                        nodePop(ctxt);
        !          5538:                        htmlnamePop(ctxt);
        !          5539:                    }
        !          5540: 
        !          5541:                    ctxt->instate = XML_PARSER_CONTENT;
        !          5542: #ifdef DEBUG_PUSH
        !          5543:                    xmlGenericError(xmlGenericErrorContext,
        !          5544:                            "HPP: entering CONTENT\n");
        !          5545: #endif
        !          5546:                    break;
        !          5547:                }
        !          5548: 
        !          5549:                /*
        !          5550:                 * Check for an Empty Element from DTD definition
        !          5551:                 */
        !          5552:                if ((info != NULL) && (info->empty)) {
        !          5553:                    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
        !          5554:                        ctxt->sax->endElement(ctxt->userData, name);
        !          5555:                    htmlnamePop(ctxt);
        !          5556:                }
        !          5557:                ctxt->instate = XML_PARSER_CONTENT;
        !          5558: #ifdef DEBUG_PUSH
        !          5559:                xmlGenericError(xmlGenericErrorContext,
        !          5560:                        "HPP: entering CONTENT\n");
        !          5561: #endif
        !          5562:                 break;
        !          5563:            }
        !          5564:             case XML_PARSER_CONTENT: {
        !          5565:                long cons;
        !          5566:                 /*
        !          5567:                 * Handle preparsed entities and charRef
        !          5568:                 */
        !          5569:                if (ctxt->token != 0) {
        !          5570:                    xmlChar chr[2] = { 0 , 0 } ;
        !          5571: 
        !          5572:                    chr[0] = (xmlChar) ctxt->token;
        !          5573:                    htmlCheckParagraph(ctxt);
        !          5574:                    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
        !          5575:                        ctxt->sax->characters(ctxt->userData, chr, 1);
        !          5576:                    ctxt->token = 0;
        !          5577:                    ctxt->checkIndex = 0;
        !          5578:                }
        !          5579:                if ((avail == 1) && (terminate)) {
        !          5580:                    cur = in->cur[0];
        !          5581:                    if ((cur != '<') && (cur != '&')) {
        !          5582:                        if (ctxt->sax != NULL) {
        !          5583:                            if (IS_BLANK_CH(cur)) {
        !          5584:                                if (ctxt->sax->ignorableWhitespace != NULL)
        !          5585:                                    ctxt->sax->ignorableWhitespace(
        !          5586:                                            ctxt->userData, &cur, 1);
        !          5587:                            } else {
        !          5588:                                htmlCheckParagraph(ctxt);
        !          5589:                                if (ctxt->sax->characters != NULL)
        !          5590:                                    ctxt->sax->characters(
        !          5591:                                            ctxt->userData, &cur, 1);
        !          5592:                            }
        !          5593:                        }
        !          5594:                        ctxt->token = 0;
        !          5595:                        ctxt->checkIndex = 0;
        !          5596:                        in->cur++;
        !          5597:                        break;
        !          5598:                    }
        !          5599:                }
        !          5600:                if (avail < 2)
        !          5601:                    goto done;
        !          5602:                cur = in->cur[0];
        !          5603:                next = in->cur[1];
        !          5604:                cons = ctxt->nbChars;
        !          5605:                if ((xmlStrEqual(ctxt->name, BAD_CAST"script")) ||
        !          5606:                    (xmlStrEqual(ctxt->name, BAD_CAST"style"))) {
        !          5607:                    /*
        !          5608:                     * Handle SCRIPT/STYLE separately
        !          5609:                     */
        !          5610:                    if (!terminate) {
        !          5611:                        int idx;
        !          5612:                        xmlChar val;
        !          5613: 
        !          5614:                        idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0, 0);
        !          5615:                        if (idx < 0)
        !          5616:                            goto done;
        !          5617:                        val = in->cur[idx + 2];
        !          5618:                        if (val == 0) /* bad cut of input */
        !          5619:                            goto done;
        !          5620:                    }
        !          5621:                    htmlParseScript(ctxt);
        !          5622:                    if ((cur == '<') && (next == '/')) {
        !          5623:                        ctxt->instate = XML_PARSER_END_TAG;
        !          5624:                        ctxt->checkIndex = 0;
        !          5625: #ifdef DEBUG_PUSH
        !          5626:                        xmlGenericError(xmlGenericErrorContext,
        !          5627:                                "HPP: entering END_TAG\n");
        !          5628: #endif
        !          5629:                        break;
        !          5630:                    }
        !          5631:                } else {
        !          5632:                    /*
        !          5633:                     * Sometimes DOCTYPE arrives in the middle of the document
        !          5634:                     */
        !          5635:                    if ((cur == '<') && (next == '!') &&
        !          5636:                        (UPP(2) == 'D') && (UPP(3) == 'O') &&
        !          5637:                        (UPP(4) == 'C') && (UPP(5) == 'T') &&
        !          5638:                        (UPP(6) == 'Y') && (UPP(7) == 'P') &&
        !          5639:                        (UPP(8) == 'E')) {
        !          5640:                        if ((!terminate) &&
        !          5641:                            (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5642:                            goto done;
        !          5643:                        htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
        !          5644:                                     "Misplaced DOCTYPE declaration\n",
        !          5645:                                     BAD_CAST "DOCTYPE" , NULL);
        !          5646:                        htmlParseDocTypeDecl(ctxt);
        !          5647:                    } else if ((cur == '<') && (next == '!') &&
        !          5648:                        (in->cur[2] == '-') && (in->cur[3] == '-')) {
        !          5649:                        if ((!terminate) &&
        !          5650:                            (htmlParseLookupSequence(
        !          5651:                                ctxt, '-', '-', '>', 1, 1) < 0))
        !          5652:                            goto done;
        !          5653: #ifdef DEBUG_PUSH
        !          5654:                        xmlGenericError(xmlGenericErrorContext,
        !          5655:                                "HPP: Parsing Comment\n");
        !          5656: #endif
        !          5657:                        htmlParseComment(ctxt);
        !          5658:                        ctxt->instate = XML_PARSER_CONTENT;
        !          5659:                    } else if ((cur == '<') && (next == '?')) {
        !          5660:                        if ((!terminate) &&
        !          5661:                            (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5662:                            goto done;
        !          5663: #ifdef DEBUG_PUSH
        !          5664:                        xmlGenericError(xmlGenericErrorContext,
        !          5665:                                "HPP: Parsing PI\n");
        !          5666: #endif
        !          5667:                        htmlParsePI(ctxt);
        !          5668:                        ctxt->instate = XML_PARSER_CONTENT;
        !          5669:                    } else if ((cur == '<') && (next == '!') && (avail < 4)) {
        !          5670:                        goto done;
        !          5671:                    } else if ((cur == '<') && (next == '/')) {
        !          5672:                        ctxt->instate = XML_PARSER_END_TAG;
        !          5673:                        ctxt->checkIndex = 0;
        !          5674: #ifdef DEBUG_PUSH
        !          5675:                        xmlGenericError(xmlGenericErrorContext,
        !          5676:                                "HPP: entering END_TAG\n");
        !          5677: #endif
        !          5678:                        break;
        !          5679:                    } else if (cur == '<') {
        !          5680:                        ctxt->instate = XML_PARSER_START_TAG;
        !          5681:                        ctxt->checkIndex = 0;
        !          5682: #ifdef DEBUG_PUSH
        !          5683:                        xmlGenericError(xmlGenericErrorContext,
        !          5684:                                "HPP: entering START_TAG\n");
        !          5685: #endif
        !          5686:                        break;
        !          5687:                    } else if (cur == '&') {
        !          5688:                        if ((!terminate) &&
        !          5689:                            (htmlParseLookupChars(ctxt,
        !          5690:                                                   BAD_CAST "; >/", 4) < 0))
        !          5691:                            goto done;
        !          5692: #ifdef DEBUG_PUSH
        !          5693:                        xmlGenericError(xmlGenericErrorContext,
        !          5694:                                "HPP: Parsing Reference\n");
        !          5695: #endif
        !          5696:                        /* TODO: check generation of subtrees if noent !!! */
        !          5697:                        htmlParseReference(ctxt);
        !          5698:                    } else {
        !          5699:                        /*
        !          5700:                         * check that the text sequence is complete
        !          5701:                         * before handing out the data to the parser
        !          5702:                         * to avoid problems with erroneous end of
        !          5703:                         * data detection.
        !          5704:                         */
        !          5705:                        if ((!terminate) &&
        !          5706:                             (htmlParseLookupChars(ctxt, BAD_CAST "<&", 2) < 0))
        !          5707:                            goto done;
        !          5708:                        ctxt->checkIndex = 0;
        !          5709: #ifdef DEBUG_PUSH
        !          5710:                        xmlGenericError(xmlGenericErrorContext,
        !          5711:                                "HPP: Parsing char data\n");
        !          5712: #endif
        !          5713:                        htmlParseCharData(ctxt);
        !          5714:                    }
        !          5715:                }
        !          5716:                if (cons == ctxt->nbChars) {
        !          5717:                    if (ctxt->node != NULL) {
        !          5718:                        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5719:                                     "detected an error in element content\n",
        !          5720:                                     NULL, NULL);
        !          5721:                    }
        !          5722:                    NEXT;
        !          5723:                    break;
        !          5724:                }
        !          5725: 
        !          5726:                break;
        !          5727:            }
        !          5728:             case XML_PARSER_END_TAG:
        !          5729:                if (avail < 2)
        !          5730:                    goto done;
        !          5731:                if ((!terminate) &&
        !          5732:                    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
        !          5733:                    goto done;
        !          5734:                htmlParseEndTag(ctxt);
        !          5735:                if (ctxt->nameNr == 0) {
        !          5736:                    ctxt->instate = XML_PARSER_EPILOG;
        !          5737:                } else {
        !          5738:                    ctxt->instate = XML_PARSER_CONTENT;
        !          5739:                }
        !          5740:                ctxt->checkIndex = 0;
        !          5741: #ifdef DEBUG_PUSH
        !          5742:                xmlGenericError(xmlGenericErrorContext,
        !          5743:                        "HPP: entering CONTENT\n");
        !          5744: #endif
        !          5745:                break;
        !          5746:             case XML_PARSER_CDATA_SECTION:
        !          5747:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5748:                        "HPP: internal error, state == CDATA\n",
        !          5749:                             NULL, NULL);
        !          5750:                ctxt->instate = XML_PARSER_CONTENT;
        !          5751:                ctxt->checkIndex = 0;
        !          5752: #ifdef DEBUG_PUSH
        !          5753:                xmlGenericError(xmlGenericErrorContext,
        !          5754:                        "HPP: entering CONTENT\n");
        !          5755: #endif
        !          5756:                break;
        !          5757:             case XML_PARSER_DTD:
        !          5758:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5759:                        "HPP: internal error, state == DTD\n",
        !          5760:                             NULL, NULL);
        !          5761:                ctxt->instate = XML_PARSER_CONTENT;
        !          5762:                ctxt->checkIndex = 0;
        !          5763: #ifdef DEBUG_PUSH
        !          5764:                xmlGenericError(xmlGenericErrorContext,
        !          5765:                        "HPP: entering CONTENT\n");
        !          5766: #endif
        !          5767:                break;
        !          5768:             case XML_PARSER_COMMENT:
        !          5769:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5770:                        "HPP: internal error, state == COMMENT\n",
        !          5771:                             NULL, NULL);
        !          5772:                ctxt->instate = XML_PARSER_CONTENT;
        !          5773:                ctxt->checkIndex = 0;
        !          5774: #ifdef DEBUG_PUSH
        !          5775:                xmlGenericError(xmlGenericErrorContext,
        !          5776:                        "HPP: entering CONTENT\n");
        !          5777: #endif
        !          5778:                break;
        !          5779:             case XML_PARSER_PI:
        !          5780:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5781:                        "HPP: internal error, state == PI\n",
        !          5782:                             NULL, NULL);
        !          5783:                ctxt->instate = XML_PARSER_CONTENT;
        !          5784:                ctxt->checkIndex = 0;
        !          5785: #ifdef DEBUG_PUSH
        !          5786:                xmlGenericError(xmlGenericErrorContext,
        !          5787:                        "HPP: entering CONTENT\n");
        !          5788: #endif
        !          5789:                break;
        !          5790:             case XML_PARSER_ENTITY_DECL:
        !          5791:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5792:                        "HPP: internal error, state == ENTITY_DECL\n",
        !          5793:                             NULL, NULL);
        !          5794:                ctxt->instate = XML_PARSER_CONTENT;
        !          5795:                ctxt->checkIndex = 0;
        !          5796: #ifdef DEBUG_PUSH
        !          5797:                xmlGenericError(xmlGenericErrorContext,
        !          5798:                        "HPP: entering CONTENT\n");
        !          5799: #endif
        !          5800:                break;
        !          5801:             case XML_PARSER_ENTITY_VALUE:
        !          5802:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5803:                        "HPP: internal error, state == ENTITY_VALUE\n",
        !          5804:                             NULL, NULL);
        !          5805:                ctxt->instate = XML_PARSER_CONTENT;
        !          5806:                ctxt->checkIndex = 0;
        !          5807: #ifdef DEBUG_PUSH
        !          5808:                xmlGenericError(xmlGenericErrorContext,
        !          5809:                        "HPP: entering DTD\n");
        !          5810: #endif
        !          5811:                break;
        !          5812:             case XML_PARSER_ATTRIBUTE_VALUE:
        !          5813:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5814:                        "HPP: internal error, state == ATTRIBUTE_VALUE\n",
        !          5815:                             NULL, NULL);
        !          5816:                ctxt->instate = XML_PARSER_START_TAG;
        !          5817:                ctxt->checkIndex = 0;
        !          5818: #ifdef DEBUG_PUSH
        !          5819:                xmlGenericError(xmlGenericErrorContext,
        !          5820:                        "HPP: entering START_TAG\n");
        !          5821: #endif
        !          5822:                break;
        !          5823:            case XML_PARSER_SYSTEM_LITERAL:
        !          5824:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5825:                    "HPP: internal error, state == XML_PARSER_SYSTEM_LITERAL\n",
        !          5826:                             NULL, NULL);
        !          5827:                ctxt->instate = XML_PARSER_CONTENT;
        !          5828:                ctxt->checkIndex = 0;
        !          5829: #ifdef DEBUG_PUSH
        !          5830:                xmlGenericError(xmlGenericErrorContext,
        !          5831:                        "HPP: entering CONTENT\n");
        !          5832: #endif
        !          5833:                break;
        !          5834:            case XML_PARSER_IGNORE:
        !          5835:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5836:                        "HPP: internal error, state == XML_PARSER_IGNORE\n",
        !          5837:                             NULL, NULL);
        !          5838:                ctxt->instate = XML_PARSER_CONTENT;
        !          5839:                ctxt->checkIndex = 0;
        !          5840: #ifdef DEBUG_PUSH
        !          5841:                xmlGenericError(xmlGenericErrorContext,
        !          5842:                        "HPP: entering CONTENT\n");
        !          5843: #endif
        !          5844:                break;
        !          5845:            case XML_PARSER_PUBLIC_LITERAL:
        !          5846:                htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5847:                        "HPP: internal error, state == XML_PARSER_LITERAL\n",
        !          5848:                             NULL, NULL);
        !          5849:                ctxt->instate = XML_PARSER_CONTENT;
        !          5850:                ctxt->checkIndex = 0;
        !          5851: #ifdef DEBUG_PUSH
        !          5852:                xmlGenericError(xmlGenericErrorContext,
        !          5853:                        "HPP: entering CONTENT\n");
        !          5854: #endif
        !          5855:                break;
        !          5856: 
        !          5857:        }
        !          5858:     }
        !          5859: done:
        !          5860:     if ((avail == 0) && (terminate)) {
        !          5861:        htmlAutoCloseOnEnd(ctxt);
        !          5862:        if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) {
        !          5863:            /*
        !          5864:             * SAX: end of the document processing.
        !          5865:             */
        !          5866:            ctxt->instate = XML_PARSER_EOF;
        !          5867:            if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
        !          5868:                ctxt->sax->endDocument(ctxt->userData);
        !          5869:        }
        !          5870:     }
        !          5871:     if ((ctxt->myDoc != NULL) &&
        !          5872:        ((terminate) || (ctxt->instate == XML_PARSER_EOF) ||
        !          5873:         (ctxt->instate == XML_PARSER_EPILOG))) {
        !          5874:        xmlDtdPtr dtd;
        !          5875:        dtd = xmlGetIntSubset(ctxt->myDoc);
        !          5876:        if (dtd == NULL)
        !          5877:            ctxt->myDoc->intSubset =
        !          5878:                xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html",
        !          5879:                    BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN",
        !          5880:                    BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd");
        !          5881:     }
        !          5882: #ifdef DEBUG_PUSH
        !          5883:     xmlGenericError(xmlGenericErrorContext, "HPP: done %d\n", ret);
        !          5884: #endif
        !          5885:     return(ret);
        !          5886: }
        !          5887: 
        !          5888: /**
        !          5889:  * htmlParseChunk:
        !          5890:  * @ctxt:  an HTML parser context
        !          5891:  * @chunk:  an char array
        !          5892:  * @size:  the size in byte of the chunk
        !          5893:  * @terminate:  last chunk indicator
        !          5894:  *
        !          5895:  * Parse a Chunk of memory
        !          5896:  *
        !          5897:  * Returns zero if no error, the xmlParserErrors otherwise.
        !          5898:  */
        !          5899: int
        !          5900: htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
        !          5901:               int terminate) {
        !          5902:     if ((ctxt == NULL) || (ctxt->input == NULL)) {
        !          5903:        htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
        !          5904:                     "htmlParseChunk: context error\n", NULL, NULL);
        !          5905:        return(XML_ERR_INTERNAL_ERROR);
        !          5906:     }
        !          5907:     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
        !          5908:         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
        !          5909:        int base = ctxt->input->base - ctxt->input->buf->buffer->content;
        !          5910:        int cur = ctxt->input->cur - ctxt->input->base;
        !          5911:        int res;
        !          5912: 
        !          5913:        res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
        !          5914:        if (res < 0) {
        !          5915:            ctxt->errNo = XML_PARSER_EOF;
        !          5916:            ctxt->disableSAX = 1;
        !          5917:            return (XML_PARSER_EOF);
        !          5918:        }
        !          5919:        ctxt->input->base = ctxt->input->buf->buffer->content + base;
        !          5920:        ctxt->input->cur = ctxt->input->base + cur;
        !          5921:        ctxt->input->end =
        !          5922:          &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
        !          5923: #ifdef DEBUG_PUSH
        !          5924:        xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
        !          5925: #endif
        !          5926: 
        !          5927: #if 0
        !          5928:        if ((terminate) || (ctxt->input->buf->buffer->use > 80))
        !          5929:            htmlParseTryOrFinish(ctxt, terminate);
        !          5930: #endif
        !          5931:     } else if (ctxt->instate != XML_PARSER_EOF) {
        !          5932:        if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
        !          5933:            xmlParserInputBufferPtr in = ctxt->input->buf;
        !          5934:            if ((in->encoder != NULL) && (in->buffer != NULL) &&
        !          5935:                    (in->raw != NULL)) {
        !          5936:                int nbchars;
        !          5937: 
        !          5938:                nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
        !          5939:                if (nbchars < 0) {
        !          5940:                    htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
        !          5941:                                 "encoder error\n", NULL, NULL);
        !          5942:                    return(XML_ERR_INVALID_ENCODING);
        !          5943:                }
        !          5944:            }
        !          5945:        }
        !          5946:     }
        !          5947:     htmlParseTryOrFinish(ctxt, terminate);
        !          5948:     if (terminate) {
        !          5949:        if ((ctxt->instate != XML_PARSER_EOF) &&
        !          5950:            (ctxt->instate != XML_PARSER_EPILOG) &&
        !          5951:            (ctxt->instate != XML_PARSER_MISC)) {
        !          5952:            ctxt->errNo = XML_ERR_DOCUMENT_END;
        !          5953:            ctxt->wellFormed = 0;
        !          5954:        }
        !          5955:        if (ctxt->instate != XML_PARSER_EOF) {
        !          5956:            if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
        !          5957:                ctxt->sax->endDocument(ctxt->userData);
        !          5958:        }
        !          5959:        ctxt->instate = XML_PARSER_EOF;
        !          5960:     }
        !          5961:     return((xmlParserErrors) ctxt->errNo);
        !          5962: }
        !          5963: 
        !          5964: /************************************************************************
        !          5965:  *                                                                     *
        !          5966:  *                     User entry points                               *
        !          5967:  *                                                                     *
        !          5968:  ************************************************************************/
        !          5969: 
        !          5970: /**
        !          5971:  * htmlCreatePushParserCtxt:
        !          5972:  * @sax:  a SAX handler
        !          5973:  * @user_data:  The user data returned on SAX callbacks
        !          5974:  * @chunk:  a pointer to an array of chars
        !          5975:  * @size:  number of chars in the array
        !          5976:  * @filename:  an optional file name or URI
        !          5977:  * @enc:  an optional encoding
        !          5978:  *
        !          5979:  * Create a parser context for using the HTML parser in push mode
        !          5980:  * The value of @filename is used for fetching external entities
        !          5981:  * and error/warning reports.
        !          5982:  *
        !          5983:  * Returns the new parser context or NULL
        !          5984:  */
        !          5985: htmlParserCtxtPtr
        !          5986: htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data,
        !          5987:                          const char *chunk, int size, const char *filename,
        !          5988:                         xmlCharEncoding enc) {
        !          5989:     htmlParserCtxtPtr ctxt;
        !          5990:     htmlParserInputPtr inputStream;
        !          5991:     xmlParserInputBufferPtr buf;
        !          5992: 
        !          5993:     xmlInitParser();
        !          5994: 
        !          5995:     buf = xmlAllocParserInputBuffer(enc);
        !          5996:     if (buf == NULL) return(NULL);
        !          5997: 
        !          5998:     ctxt = htmlNewParserCtxt();
        !          5999:     if (ctxt == NULL) {
        !          6000:        xmlFreeParserInputBuffer(buf);
        !          6001:        return(NULL);
        !          6002:     }
        !          6003:     if(enc==XML_CHAR_ENCODING_UTF8 || buf->encoder)
        !          6004:        ctxt->charset=XML_CHAR_ENCODING_UTF8;
        !          6005:     if (sax != NULL) {
        !          6006:        if (ctxt->sax != (xmlSAXHandlerPtr) &htmlDefaultSAXHandler)
        !          6007:            xmlFree(ctxt->sax);
        !          6008:        ctxt->sax = (htmlSAXHandlerPtr) xmlMalloc(sizeof(htmlSAXHandler));
        !          6009:        if (ctxt->sax == NULL) {
        !          6010:            xmlFree(buf);
        !          6011:            xmlFree(ctxt);
        !          6012:            return(NULL);
        !          6013:        }
        !          6014:        memcpy(ctxt->sax, sax, sizeof(htmlSAXHandler));
        !          6015:        if (user_data != NULL)
        !          6016:            ctxt->userData = user_data;
        !          6017:     }
        !          6018:     if (filename == NULL) {
        !          6019:        ctxt->directory = NULL;
        !          6020:     } else {
        !          6021:         ctxt->directory = xmlParserGetDirectory(filename);
        !          6022:     }
        !          6023: 
        !          6024:     inputStream = htmlNewInputStream(ctxt);
        !          6025:     if (inputStream == NULL) {
        !          6026:        xmlFreeParserCtxt(ctxt);
        !          6027:        xmlFree(buf);
        !          6028:        return(NULL);
        !          6029:     }
        !          6030: 
        !          6031:     if (filename == NULL)
        !          6032:        inputStream->filename = NULL;
        !          6033:     else
        !          6034:        inputStream->filename = (char *)
        !          6035:            xmlCanonicPath((const xmlChar *) filename);
        !          6036:     inputStream->buf = buf;
        !          6037:     inputStream->base = inputStream->buf->buffer->content;
        !          6038:     inputStream->cur = inputStream->buf->buffer->content;
        !          6039:     inputStream->end =
        !          6040:        &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
        !          6041: 
        !          6042:     inputPush(ctxt, inputStream);
        !          6043: 
        !          6044:     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
        !          6045:         (ctxt->input->buf != NULL))  {
        !          6046:        int base = ctxt->input->base - ctxt->input->buf->buffer->content;
        !          6047:        int cur = ctxt->input->cur - ctxt->input->base;
        !          6048: 
        !          6049:        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
        !          6050: 
        !          6051:        ctxt->input->base = ctxt->input->buf->buffer->content + base;
        !          6052:        ctxt->input->cur = ctxt->input->base + cur;
        !          6053:        ctxt->input->end =
        !          6054:            &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
        !          6055: #ifdef DEBUG_PUSH
        !          6056:        xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
        !          6057: #endif
        !          6058:     }
        !          6059:     ctxt->progressive = 1;
        !          6060: 
        !          6061:     return(ctxt);
        !          6062: }
        !          6063: #endif /* LIBXML_PUSH_ENABLED */
        !          6064: 
        !          6065: /**
        !          6066:  * htmlSAXParseDoc:
        !          6067:  * @cur:  a pointer to an array of xmlChar
        !          6068:  * @encoding:  a free form C string describing the HTML document encoding, or NULL
        !          6069:  * @sax:  the SAX handler block
        !          6070:  * @userData: if using SAX, this pointer will be provided on callbacks.
        !          6071:  *
        !          6072:  * Parse an HTML in-memory document. If sax is not NULL, use the SAX callbacks
        !          6073:  * to handle parse events. If sax is NULL, fallback to the default DOM
        !          6074:  * behavior and return a tree.
        !          6075:  *
        !          6076:  * Returns the resulting document tree unless SAX is NULL or the document is
        !          6077:  *     not well formed.
        !          6078:  */
        !          6079: 
        !          6080: htmlDocPtr
        !          6081: htmlSAXParseDoc(xmlChar *cur, const char *encoding, htmlSAXHandlerPtr sax, void *userData) {
        !          6082:     htmlDocPtr ret;
        !          6083:     htmlParserCtxtPtr ctxt;
        !          6084: 
        !          6085:     xmlInitParser();
        !          6086: 
        !          6087:     if (cur == NULL) return(NULL);
        !          6088: 
        !          6089: 
        !          6090:     ctxt = htmlCreateDocParserCtxt(cur, encoding);
        !          6091:     if (ctxt == NULL) return(NULL);
        !          6092:     if (sax != NULL) {
        !          6093:         if (ctxt->sax != NULL) xmlFree (ctxt->sax);
        !          6094:         ctxt->sax = sax;
        !          6095:         ctxt->userData = userData;
        !          6096:     }
        !          6097: 
        !          6098:     htmlParseDocument(ctxt);
        !          6099:     ret = ctxt->myDoc;
        !          6100:     if (sax != NULL) {
        !          6101:        ctxt->sax = NULL;
        !          6102:        ctxt->userData = NULL;
        !          6103:     }
        !          6104:     htmlFreeParserCtxt(ctxt);
        !          6105: 
        !          6106:     return(ret);
        !          6107: }
        !          6108: 
        !          6109: /**
        !          6110:  * htmlParseDoc:
        !          6111:  * @cur:  a pointer to an array of xmlChar
        !          6112:  * @encoding:  a free form C string describing the HTML document encoding, or NULL
        !          6113:  *
        !          6114:  * parse an HTML in-memory document and build a tree.
        !          6115:  *
        !          6116:  * Returns the resulting document tree
        !          6117:  */
        !          6118: 
        !          6119: htmlDocPtr
        !          6120: htmlParseDoc(xmlChar *cur, const char *encoding) {
        !          6121:     return(htmlSAXParseDoc(cur, encoding, NULL, NULL));
        !          6122: }
        !          6123: 
        !          6124: 
        !          6125: /**
        !          6126:  * htmlCreateFileParserCtxt:
        !          6127:  * @filename:  the filename
        !          6128:  * @encoding:  a free form C string describing the HTML document encoding, or NULL
        !          6129:  *
        !          6130:  * Create a parser context for a file content.
        !          6131:  * Automatic support for ZLIB/Compress compressed document is provided
        !          6132:  * by default if found at compile-time.
        !          6133:  *
        !          6134:  * Returns the new parser context or NULL
        !          6135:  */
        !          6136: htmlParserCtxtPtr
        !          6137: htmlCreateFileParserCtxt(const char *filename, const char *encoding)
        !          6138: {
        !          6139:     htmlParserCtxtPtr ctxt;
        !          6140:     htmlParserInputPtr inputStream;
        !          6141:     char *canonicFilename;
        !          6142:     /* htmlCharEncoding enc; */
        !          6143:     xmlChar *content, *content_line = (xmlChar *) "charset=";
        !          6144: 
        !          6145:     if (filename == NULL)
        !          6146:         return(NULL);
        !          6147: 
        !          6148:     ctxt = htmlNewParserCtxt();
        !          6149:     if (ctxt == NULL) {
        !          6150:        return(NULL);
        !          6151:     }
        !          6152:     canonicFilename = (char *) xmlCanonicPath((const xmlChar *) filename);
        !          6153:     if (canonicFilename == NULL) {
        !          6154: #ifdef LIBXML_SAX1_ENABLED
        !          6155:        if (xmlDefaultSAXHandler.error != NULL) {
        !          6156:            xmlDefaultSAXHandler.error(NULL, "out of memory\n");
        !          6157:        }
        !          6158: #endif
        !          6159:        xmlFreeParserCtxt(ctxt);
        !          6160:        return(NULL);
        !          6161:     }
        !          6162: 
        !          6163:     inputStream = xmlLoadExternalEntity(canonicFilename, NULL, ctxt);
        !          6164:     xmlFree(canonicFilename);
        !          6165:     if (inputStream == NULL) {
        !          6166:        xmlFreeParserCtxt(ctxt);
        !          6167:        return(NULL);
        !          6168:     }
        !          6169: 
        !          6170:     inputPush(ctxt, inputStream);
        !          6171: 
        !          6172:     /* set encoding */
        !          6173:     if (encoding) {
        !          6174:         content = xmlMallocAtomic (xmlStrlen(content_line) + strlen(encoding) + 1);
        !          6175:        if (content) {
        !          6176:            strcpy ((char *)content, (char *)content_line);
        !          6177:             strcat ((char *)content, (char *)encoding);
        !          6178:             htmlCheckEncoding (ctxt, content);
        !          6179:            xmlFree (content);
        !          6180:        }
        !          6181:     }
        !          6182: 
        !          6183:     return(ctxt);
        !          6184: }
        !          6185: 
        !          6186: /**
        !          6187:  * htmlSAXParseFile:
        !          6188:  * @filename:  the filename
        !          6189:  * @encoding:  a free form C string describing the HTML document encoding, or NULL
        !          6190:  * @sax:  the SAX handler block
        !          6191:  * @userData: if using SAX, this pointer will be provided on callbacks.
        !          6192:  *
        !          6193:  * parse an HTML file and build a tree. Automatic support for ZLIB/Compress
        !          6194:  * compressed document is provided by default if found at compile-time.
        !          6195:  * It use the given SAX function block to handle the parsing callback.
        !          6196:  * If sax is NULL, fallback to the default DOM tree building routines.
        !          6197:  *
        !          6198:  * Returns the resulting document tree unless SAX is NULL or the document is
        !          6199:  *     not well formed.
        !          6200:  */
        !          6201: 
        !          6202: htmlDocPtr
        !          6203: htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr sax,
        !          6204:                  void *userData) {
        !          6205:     htmlDocPtr ret;
        !          6206:     htmlParserCtxtPtr ctxt;
        !          6207:     htmlSAXHandlerPtr oldsax = NULL;
        !          6208: 
        !          6209:     xmlInitParser();
        !          6210: 
        !          6211:     ctxt = htmlCreateFileParserCtxt(filename, encoding);
        !          6212:     if (ctxt == NULL) return(NULL);
        !          6213:     if (sax != NULL) {
        !          6214:        oldsax = ctxt->sax;
        !          6215:         ctxt->sax = sax;
        !          6216:         ctxt->userData = userData;
        !          6217:     }
        !          6218: 
        !          6219:     htmlParseDocument(ctxt);
        !          6220: 
        !          6221:     ret = ctxt->myDoc;
        !          6222:     if (sax != NULL) {
        !          6223:         ctxt->sax = oldsax;
        !          6224:         ctxt->userData = NULL;
        !          6225:     }
        !          6226:     htmlFreeParserCtxt(ctxt);
        !          6227: 
        !          6228:     return(ret);
        !          6229: }
        !          6230: 
        !          6231: /**
        !          6232:  * htmlParseFile:
        !          6233:  * @filename:  the filename
        !          6234:  * @encoding:  a free form C string describing the HTML document encoding, or NULL
        !          6235:  *
        !          6236:  * parse an HTML file and build a tree. Automatic support for ZLIB/Compress
        !          6237:  * compressed document is provided by default if found at compile-time.
        !          6238:  *
        !          6239:  * Returns the resulting document tree
        !          6240:  */
        !          6241: 
        !          6242: htmlDocPtr
        !          6243: htmlParseFile(const char *filename, const char *encoding) {
        !          6244:     return(htmlSAXParseFile(filename, encoding, NULL, NULL));
        !          6245: }
        !          6246: 
        !          6247: /**
        !          6248:  * htmlHandleOmittedElem:
        !          6249:  * @val:  int 0 or 1
        !          6250:  *
        !          6251:  * Set and return the previous value for handling HTML omitted tags.
        !          6252:  *
        !          6253:  * Returns the last value for 0 for no handling, 1 for auto insertion.
        !          6254:  */
        !          6255: 
        !          6256: int
        !          6257: htmlHandleOmittedElem(int val) {
        !          6258:     int old = htmlOmittedDefaultValue;
        !          6259: 
        !          6260:     htmlOmittedDefaultValue = val;
        !          6261:     return(old);
        !          6262: }
        !          6263: 
        !          6264: /**
        !          6265:  * htmlElementAllowedHere:
        !          6266:  * @parent: HTML parent element
        !          6267:  * @elt: HTML element
        !          6268:  *
        !          6269:  * Checks whether an HTML element may be a direct child of a parent element.
        !          6270:  * Note - doesn't check for deprecated elements
        !          6271:  *
        !          6272:  * Returns 1 if allowed; 0 otherwise.
        !          6273:  */
        !          6274: int
        !          6275: htmlElementAllowedHere(const htmlElemDesc* parent, const xmlChar* elt) {
        !          6276:   const char** p ;
        !          6277: 
        !          6278:   if ( ! elt || ! parent || ! parent->subelts )
        !          6279:        return 0 ;
        !          6280: 
        !          6281:   for ( p = parent->subelts; *p; ++p )
        !          6282:     if ( !xmlStrcmp((const xmlChar *)*p, elt) )
        !          6283:       return 1 ;
        !          6284: 
        !          6285:   return 0 ;
        !          6286: }
        !          6287: /**
        !          6288:  * htmlElementStatusHere:
        !          6289:  * @parent: HTML parent element
        !          6290:  * @elt: HTML element
        !          6291:  *
        !          6292:  * Checks whether an HTML element may be a direct child of a parent element.
        !          6293:  * and if so whether it is valid or deprecated.
        !          6294:  *
        !          6295:  * Returns one of HTML_VALID, HTML_DEPRECATED, HTML_INVALID
        !          6296:  */
        !          6297: htmlStatus
        !          6298: htmlElementStatusHere(const htmlElemDesc* parent, const htmlElemDesc* elt) {
        !          6299:   if ( ! parent || ! elt )
        !          6300:     return HTML_INVALID ;
        !          6301:   if ( ! htmlElementAllowedHere(parent, (const xmlChar*) elt->name ) )
        !          6302:     return HTML_INVALID ;
        !          6303: 
        !          6304:   return ( elt->dtd == 0 ) ? HTML_VALID : HTML_DEPRECATED ;
        !          6305: }
        !          6306: /**
        !          6307:  * htmlAttrAllowed:
        !          6308:  * @elt: HTML element
        !          6309:  * @attr: HTML attribute
        !          6310:  * @legacy: whether to allow deprecated attributes
        !          6311:  *
        !          6312:  * Checks whether an attribute is valid for an element
        !          6313:  * Has full knowledge of Required and Deprecated attributes
        !          6314:  *
        !          6315:  * Returns one of HTML_REQUIRED, HTML_VALID, HTML_DEPRECATED, HTML_INVALID
        !          6316:  */
        !          6317: htmlStatus
        !          6318: htmlAttrAllowed(const htmlElemDesc* elt, const xmlChar* attr, int legacy) {
        !          6319:   const char** p ;
        !          6320: 
        !          6321:   if ( !elt || ! attr )
        !          6322:        return HTML_INVALID ;
        !          6323: 
        !          6324:   if ( elt->attrs_req )
        !          6325:     for ( p = elt->attrs_req; *p; ++p)
        !          6326:       if ( !xmlStrcmp((const xmlChar*)*p, attr) )
        !          6327:         return HTML_REQUIRED ;
        !          6328: 
        !          6329:   if ( elt->attrs_opt )
        !          6330:     for ( p = elt->attrs_opt; *p; ++p)
        !          6331:       if ( !xmlStrcmp((const xmlChar*)*p, attr) )
        !          6332:         return HTML_VALID ;
        !          6333: 
        !          6334:   if ( legacy && elt->attrs_depr )
        !          6335:     for ( p = elt->attrs_depr; *p; ++p)
        !          6336:       if ( !xmlStrcmp((const xmlChar*)*p, attr) )
        !          6337:         return HTML_DEPRECATED ;
        !          6338: 
        !          6339:   return HTML_INVALID ;
        !          6340: }
        !          6341: /**
        !          6342:  * htmlNodeStatus:
        !          6343:  * @node: an htmlNodePtr in a tree
        !          6344:  * @legacy: whether to allow deprecated elements (YES is faster here
        !          6345:  *     for Element nodes)
        !          6346:  *
        !          6347:  * Checks whether the tree node is valid.  Experimental (the author
        !          6348:  *     only uses the HTML enhancements in a SAX parser)
        !          6349:  *
        !          6350:  * Return: for Element nodes, a return from htmlElementAllowedHere (if
        !          6351:  *     legacy allowed) or htmlElementStatusHere (otherwise).
        !          6352:  *     for Attribute nodes, a return from htmlAttrAllowed
        !          6353:  *     for other nodes, HTML_NA (no checks performed)
        !          6354:  */
        !          6355: htmlStatus
        !          6356: htmlNodeStatus(const htmlNodePtr node, int legacy) {
        !          6357:   if ( ! node )
        !          6358:     return HTML_INVALID ;
        !          6359: 
        !          6360:   switch ( node->type ) {
        !          6361:     case XML_ELEMENT_NODE:
        !          6362:       return legacy
        !          6363:        ? ( htmlElementAllowedHere (
        !          6364:                htmlTagLookup(node->parent->name) , node->name
        !          6365:                ) ? HTML_VALID : HTML_INVALID )
        !          6366:        : htmlElementStatusHere(
        !          6367:                htmlTagLookup(node->parent->name) ,
        !          6368:                htmlTagLookup(node->name) )
        !          6369:        ;
        !          6370:     case XML_ATTRIBUTE_NODE:
        !          6371:       return htmlAttrAllowed(
        !          6372:        htmlTagLookup(node->parent->name) , node->name, legacy) ;
        !          6373:     default: return HTML_NA ;
        !          6374:   }
        !          6375: }
        !          6376: /************************************************************************
        !          6377:  *                                                                     *
        !          6378:  *     New set (2.6.0) of simpler and more flexible APIs               *
        !          6379:  *                                                                     *
        !          6380:  ************************************************************************/
        !          6381: /**
        !          6382:  * DICT_FREE:
        !          6383:  * @str:  a string
        !          6384:  *
        !          6385:  * Free a string if it is not owned by the "dict" dictionnary in the
        !          6386:  * current scope
        !          6387:  */
        !          6388: #define DICT_FREE(str)                                         \
        !          6389:        if ((str) && ((!dict) ||                                \
        !          6390:            (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
        !          6391:            xmlFree((char *)(str));
        !          6392: 
        !          6393: /**
        !          6394:  * htmlCtxtReset:
        !          6395:  * @ctxt: an HTML parser context
        !          6396:  *
        !          6397:  * Reset a parser context
        !          6398:  */
        !          6399: void
        !          6400: htmlCtxtReset(htmlParserCtxtPtr ctxt)
        !          6401: {
        !          6402:     xmlParserInputPtr input;
        !          6403:     xmlDictPtr dict;
        !          6404: 
        !          6405:     if (ctxt == NULL)
        !          6406:         return;
        !          6407: 
        !          6408:     xmlInitParser();
        !          6409:     dict = ctxt->dict;
        !          6410: 
        !          6411:     while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
        !          6412:         xmlFreeInputStream(input);
        !          6413:     }
        !          6414:     ctxt->inputNr = 0;
        !          6415:     ctxt->input = NULL;
        !          6416: 
        !          6417:     ctxt->spaceNr = 0;
        !          6418:     if (ctxt->spaceTab != NULL) {
        !          6419:        ctxt->spaceTab[0] = -1;
        !          6420:        ctxt->space = &ctxt->spaceTab[0];
        !          6421:     } else {
        !          6422:        ctxt->space = NULL;
        !          6423:     }
        !          6424: 
        !          6425: 
        !          6426:     ctxt->nodeNr = 0;
        !          6427:     ctxt->node = NULL;
        !          6428: 
        !          6429:     ctxt->nameNr = 0;
        !          6430:     ctxt->name = NULL;
        !          6431: 
        !          6432:     DICT_FREE(ctxt->version);
        !          6433:     ctxt->version = NULL;
        !          6434:     DICT_FREE(ctxt->encoding);
        !          6435:     ctxt->encoding = NULL;
        !          6436:     DICT_FREE(ctxt->directory);
        !          6437:     ctxt->directory = NULL;
        !          6438:     DICT_FREE(ctxt->extSubURI);
        !          6439:     ctxt->extSubURI = NULL;
        !          6440:     DICT_FREE(ctxt->extSubSystem);
        !          6441:     ctxt->extSubSystem = NULL;
        !          6442:     if (ctxt->myDoc != NULL)
        !          6443:         xmlFreeDoc(ctxt->myDoc);
        !          6444:     ctxt->myDoc = NULL;
        !          6445: 
        !          6446:     ctxt->standalone = -1;
        !          6447:     ctxt->hasExternalSubset = 0;
        !          6448:     ctxt->hasPErefs = 0;
        !          6449:     ctxt->html = 1;
        !          6450:     ctxt->external = 0;
        !          6451:     ctxt->instate = XML_PARSER_START;
        !          6452:     ctxt->token = 0;
        !          6453: 
        !          6454:     ctxt->wellFormed = 1;
        !          6455:     ctxt->nsWellFormed = 1;
        !          6456:     ctxt->disableSAX = 0;
        !          6457:     ctxt->valid = 1;
        !          6458:     ctxt->vctxt.userData = ctxt;
        !          6459:     ctxt->vctxt.error = xmlParserValidityError;
        !          6460:     ctxt->vctxt.warning = xmlParserValidityWarning;
        !          6461:     ctxt->record_info = 0;
        !          6462:     ctxt->nbChars = 0;
        !          6463:     ctxt->checkIndex = 0;
        !          6464:     ctxt->inSubset = 0;
        !          6465:     ctxt->errNo = XML_ERR_OK;
        !          6466:     ctxt->depth = 0;
        !          6467:     ctxt->charset = XML_CHAR_ENCODING_NONE;
        !          6468:     ctxt->catalogs = NULL;
        !          6469:     xmlInitNodeInfoSeq(&ctxt->node_seq);
        !          6470: 
        !          6471:     if (ctxt->attsDefault != NULL) {
        !          6472:         xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
        !          6473:         ctxt->attsDefault = NULL;
        !          6474:     }
        !          6475:     if (ctxt->attsSpecial != NULL) {
        !          6476:         xmlHashFree(ctxt->attsSpecial, NULL);
        !          6477:         ctxt->attsSpecial = NULL;
        !          6478:     }
        !          6479: }
        !          6480: 
        !          6481: /**
        !          6482:  * htmlCtxtUseOptions:
        !          6483:  * @ctxt: an HTML parser context
        !          6484:  * @options:  a combination of htmlParserOption(s)
        !          6485:  *
        !          6486:  * Applies the options to the parser context
        !          6487:  *
        !          6488:  * Returns 0 in case of success, the set of unknown or unimplemented options
        !          6489:  *         in case of error.
        !          6490:  */
        !          6491: int
        !          6492: htmlCtxtUseOptions(htmlParserCtxtPtr ctxt, int options)
        !          6493: {
        !          6494:     if (ctxt == NULL)
        !          6495:         return(-1);
        !          6496: 
        !          6497:     if (options & HTML_PARSE_NOWARNING) {
        !          6498:         ctxt->sax->warning = NULL;
        !          6499:         ctxt->vctxt.warning = NULL;
        !          6500:         options -= XML_PARSE_NOWARNING;
        !          6501:        ctxt->options |= XML_PARSE_NOWARNING;
        !          6502:     }
        !          6503:     if (options & HTML_PARSE_NOERROR) {
        !          6504:         ctxt->sax->error = NULL;
        !          6505:         ctxt->vctxt.error = NULL;
        !          6506:         ctxt->sax->fatalError = NULL;
        !          6507:         options -= XML_PARSE_NOERROR;
        !          6508:        ctxt->options |= XML_PARSE_NOERROR;
        !          6509:     }
        !          6510:     if (options & HTML_PARSE_PEDANTIC) {
        !          6511:         ctxt->pedantic = 1;
        !          6512:         options -= XML_PARSE_PEDANTIC;
        !          6513:        ctxt->options |= XML_PARSE_PEDANTIC;
        !          6514:     } else
        !          6515:         ctxt->pedantic = 0;
        !          6516:     if (options & XML_PARSE_NOBLANKS) {
        !          6517:         ctxt->keepBlanks = 0;
        !          6518:         ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
        !          6519:         options -= XML_PARSE_NOBLANKS;
        !          6520:        ctxt->options |= XML_PARSE_NOBLANKS;
        !          6521:     } else
        !          6522:         ctxt->keepBlanks = 1;
        !          6523:     if (options & HTML_PARSE_RECOVER) {
        !          6524:         ctxt->recovery = 1;
        !          6525:        options -= HTML_PARSE_RECOVER;
        !          6526:     } else
        !          6527:         ctxt->recovery = 0;
        !          6528:     if (options & HTML_PARSE_COMPACT) {
        !          6529:        ctxt->options |= HTML_PARSE_COMPACT;
        !          6530:         options -= HTML_PARSE_COMPACT;
        !          6531:     }
        !          6532:     if (options & XML_PARSE_HUGE) {
        !          6533:        ctxt->options |= XML_PARSE_HUGE;
        !          6534:         options -= XML_PARSE_HUGE;
        !          6535:     }
        !          6536:     if (options & HTML_PARSE_NODEFDTD) {
        !          6537:        ctxt->options |= HTML_PARSE_NODEFDTD;
        !          6538:         options -= HTML_PARSE_NODEFDTD;
        !          6539:     }
        !          6540:     ctxt->dictNames = 0;
        !          6541:     return (options);
        !          6542: }
        !          6543: 
        !          6544: /**
        !          6545:  * htmlDoRead:
        !          6546:  * @ctxt:  an HTML parser context
        !          6547:  * @URL:  the base URL to use for the document
        !          6548:  * @encoding:  the document encoding, or NULL
        !          6549:  * @options:  a combination of htmlParserOption(s)
        !          6550:  * @reuse:  keep the context for reuse
        !          6551:  *
        !          6552:  * Common front-end for the htmlRead functions
        !          6553:  *
        !          6554:  * Returns the resulting document tree or NULL
        !          6555:  */
        !          6556: static htmlDocPtr
        !          6557: htmlDoRead(htmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
        !          6558:           int options, int reuse)
        !          6559: {
        !          6560:     htmlDocPtr ret;
        !          6561: 
        !          6562:     htmlCtxtUseOptions(ctxt, options);
        !          6563:     ctxt->html = 1;
        !          6564:     if (encoding != NULL) {
        !          6565:         xmlCharEncodingHandlerPtr hdlr;
        !          6566: 
        !          6567:        hdlr = xmlFindCharEncodingHandler(encoding);
        !          6568:        if (hdlr != NULL) {
        !          6569:            xmlSwitchToEncoding(ctxt, hdlr);
        !          6570:            if (ctxt->input->encoding != NULL)
        !          6571:              xmlFree((xmlChar *) ctxt->input->encoding);
        !          6572:             ctxt->input->encoding = xmlStrdup((xmlChar *)encoding);
        !          6573:         }
        !          6574:     }
        !          6575:     if ((URL != NULL) && (ctxt->input != NULL) &&
        !          6576:         (ctxt->input->filename == NULL))
        !          6577:         ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
        !          6578:     htmlParseDocument(ctxt);
        !          6579:     ret = ctxt->myDoc;
        !          6580:     ctxt->myDoc = NULL;
        !          6581:     if (!reuse) {
        !          6582:         if ((ctxt->dictNames) &&
        !          6583:            (ret != NULL) &&
        !          6584:            (ret->dict == ctxt->dict))
        !          6585:            ctxt->dict = NULL;
        !          6586:        xmlFreeParserCtxt(ctxt);
        !          6587:     }
        !          6588:     return (ret);
        !          6589: }
        !          6590: 
        !          6591: /**
        !          6592:  * htmlReadDoc:
        !          6593:  * @cur:  a pointer to a zero terminated string
        !          6594:  * @URL:  the base URL to use for the document
        !          6595:  * @encoding:  the document encoding, or NULL
        !          6596:  * @options:  a combination of htmlParserOption(s)
        !          6597:  *
        !          6598:  * parse an XML in-memory document and build a tree.
        !          6599:  *
        !          6600:  * Returns the resulting document tree
        !          6601:  */
        !          6602: htmlDocPtr
        !          6603: htmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
        !          6604: {
        !          6605:     htmlParserCtxtPtr ctxt;
        !          6606: 
        !          6607:     if (cur == NULL)
        !          6608:         return (NULL);
        !          6609: 
        !          6610:     xmlInitParser();
        !          6611:     ctxt = htmlCreateDocParserCtxt(cur, NULL);
        !          6612:     if (ctxt == NULL)
        !          6613:         return (NULL);
        !          6614:     return (htmlDoRead(ctxt, URL, encoding, options, 0));
        !          6615: }
        !          6616: 
        !          6617: /**
        !          6618:  * htmlReadFile:
        !          6619:  * @filename:  a file or URL
        !          6620:  * @encoding:  the document encoding, or NULL
        !          6621:  * @options:  a combination of htmlParserOption(s)
        !          6622:  *
        !          6623:  * parse an XML file from the filesystem or the network.
        !          6624:  *
        !          6625:  * Returns the resulting document tree
        !          6626:  */
        !          6627: htmlDocPtr
        !          6628: htmlReadFile(const char *filename, const char *encoding, int options)
        !          6629: {
        !          6630:     htmlParserCtxtPtr ctxt;
        !          6631: 
        !          6632:     xmlInitParser();
        !          6633:     ctxt = htmlCreateFileParserCtxt(filename, encoding);
        !          6634:     if (ctxt == NULL)
        !          6635:         return (NULL);
        !          6636:     return (htmlDoRead(ctxt, NULL, NULL, options, 0));
        !          6637: }
        !          6638: 
        !          6639: /**
        !          6640:  * htmlReadMemory:
        !          6641:  * @buffer:  a pointer to a char array
        !          6642:  * @size:  the size of the array
        !          6643:  * @URL:  the base URL to use for the document
        !          6644:  * @encoding:  the document encoding, or NULL
        !          6645:  * @options:  a combination of htmlParserOption(s)
        !          6646:  *
        !          6647:  * parse an XML in-memory document and build a tree.
        !          6648:  *
        !          6649:  * Returns the resulting document tree
        !          6650:  */
        !          6651: htmlDocPtr
        !          6652: htmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
        !          6653: {
        !          6654:     htmlParserCtxtPtr ctxt;
        !          6655: 
        !          6656:     xmlInitParser();
        !          6657:     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
        !          6658:     if (ctxt == NULL)
        !          6659:         return (NULL);
        !          6660:     htmlDefaultSAXHandlerInit();
        !          6661:     if (ctxt->sax != NULL)
        !          6662:         memcpy(ctxt->sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1));
        !          6663:     return (htmlDoRead(ctxt, URL, encoding, options, 0));
        !          6664: }
        !          6665: 
        !          6666: /**
        !          6667:  * htmlReadFd:
        !          6668:  * @fd:  an open file descriptor
        !          6669:  * @URL:  the base URL to use for the document
        !          6670:  * @encoding:  the document encoding, or NULL
        !          6671:  * @options:  a combination of htmlParserOption(s)
        !          6672:  *
        !          6673:  * parse an XML from a file descriptor and build a tree.
        !          6674:  *
        !          6675:  * Returns the resulting document tree
        !          6676:  */
        !          6677: htmlDocPtr
        !          6678: htmlReadFd(int fd, const char *URL, const char *encoding, int options)
        !          6679: {
        !          6680:     htmlParserCtxtPtr ctxt;
        !          6681:     xmlParserInputBufferPtr input;
        !          6682:     xmlParserInputPtr stream;
        !          6683: 
        !          6684:     if (fd < 0)
        !          6685:         return (NULL);
        !          6686: 
        !          6687:     xmlInitParser();
        !          6688:     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
        !          6689:     if (input == NULL)
        !          6690:         return (NULL);
        !          6691:     ctxt = xmlNewParserCtxt();
        !          6692:     if (ctxt == NULL) {
        !          6693:         xmlFreeParserInputBuffer(input);
        !          6694:         return (NULL);
        !          6695:     }
        !          6696:     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
        !          6697:     if (stream == NULL) {
        !          6698:         xmlFreeParserInputBuffer(input);
        !          6699:        xmlFreeParserCtxt(ctxt);
        !          6700:         return (NULL);
        !          6701:     }
        !          6702:     inputPush(ctxt, stream);
        !          6703:     return (htmlDoRead(ctxt, URL, encoding, options, 0));
        !          6704: }
        !          6705: 
        !          6706: /**
        !          6707:  * htmlReadIO:
        !          6708:  * @ioread:  an I/O read function
        !          6709:  * @ioclose:  an I/O close function
        !          6710:  * @ioctx:  an I/O handler
        !          6711:  * @URL:  the base URL to use for the document
        !          6712:  * @encoding:  the document encoding, or NULL
        !          6713:  * @options:  a combination of htmlParserOption(s)
        !          6714:  *
        !          6715:  * parse an HTML document from I/O functions and source and build a tree.
        !          6716:  *
        !          6717:  * Returns the resulting document tree
        !          6718:  */
        !          6719: htmlDocPtr
        !          6720: htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
        !          6721:           void *ioctx, const char *URL, const char *encoding, int options)
        !          6722: {
        !          6723:     htmlParserCtxtPtr ctxt;
        !          6724:     xmlParserInputBufferPtr input;
        !          6725:     xmlParserInputPtr stream;
        !          6726: 
        !          6727:     if (ioread == NULL)
        !          6728:         return (NULL);
        !          6729:     xmlInitParser();
        !          6730: 
        !          6731:     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
        !          6732:                                          XML_CHAR_ENCODING_NONE);
        !          6733:     if (input == NULL)
        !          6734:         return (NULL);
        !          6735:     ctxt = htmlNewParserCtxt();
        !          6736:     if (ctxt == NULL) {
        !          6737:         xmlFreeParserInputBuffer(input);
        !          6738:         return (NULL);
        !          6739:     }
        !          6740:     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
        !          6741:     if (stream == NULL) {
        !          6742:         xmlFreeParserInputBuffer(input);
        !          6743:        xmlFreeParserCtxt(ctxt);
        !          6744:         return (NULL);
        !          6745:     }
        !          6746:     inputPush(ctxt, stream);
        !          6747:     return (htmlDoRead(ctxt, URL, encoding, options, 0));
        !          6748: }
        !          6749: 
        !          6750: /**
        !          6751:  * htmlCtxtReadDoc:
        !          6752:  * @ctxt:  an HTML parser context
        !          6753:  * @cur:  a pointer to a zero terminated string
        !          6754:  * @URL:  the base URL to use for the document
        !          6755:  * @encoding:  the document encoding, or NULL
        !          6756:  * @options:  a combination of htmlParserOption(s)
        !          6757:  *
        !          6758:  * parse an XML in-memory document and build a tree.
        !          6759:  * This reuses the existing @ctxt parser context
        !          6760:  *
        !          6761:  * Returns the resulting document tree
        !          6762:  */
        !          6763: htmlDocPtr
        !          6764: htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar * cur,
        !          6765:                const char *URL, const char *encoding, int options)
        !          6766: {
        !          6767:     xmlParserInputPtr stream;
        !          6768: 
        !          6769:     if (cur == NULL)
        !          6770:         return (NULL);
        !          6771:     if (ctxt == NULL)
        !          6772:         return (NULL);
        !          6773: 
        !          6774:     htmlCtxtReset(ctxt);
        !          6775: 
        !          6776:     stream = xmlNewStringInputStream(ctxt, cur);
        !          6777:     if (stream == NULL) {
        !          6778:         return (NULL);
        !          6779:     }
        !          6780:     inputPush(ctxt, stream);
        !          6781:     return (htmlDoRead(ctxt, URL, encoding, options, 1));
        !          6782: }
        !          6783: 
        !          6784: /**
        !          6785:  * htmlCtxtReadFile:
        !          6786:  * @ctxt:  an HTML parser context
        !          6787:  * @filename:  a file or URL
        !          6788:  * @encoding:  the document encoding, or NULL
        !          6789:  * @options:  a combination of htmlParserOption(s)
        !          6790:  *
        !          6791:  * parse an XML file from the filesystem or the network.
        !          6792:  * This reuses the existing @ctxt parser context
        !          6793:  *
        !          6794:  * Returns the resulting document tree
        !          6795:  */
        !          6796: htmlDocPtr
        !          6797: htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename,
        !          6798:                 const char *encoding, int options)
        !          6799: {
        !          6800:     xmlParserInputPtr stream;
        !          6801: 
        !          6802:     if (filename == NULL)
        !          6803:         return (NULL);
        !          6804:     if (ctxt == NULL)
        !          6805:         return (NULL);
        !          6806: 
        !          6807:     htmlCtxtReset(ctxt);
        !          6808: 
        !          6809:     stream = xmlLoadExternalEntity(filename, NULL, ctxt);
        !          6810:     if (stream == NULL) {
        !          6811:         return (NULL);
        !          6812:     }
        !          6813:     inputPush(ctxt, stream);
        !          6814:     return (htmlDoRead(ctxt, NULL, encoding, options, 1));
        !          6815: }
        !          6816: 
        !          6817: /**
        !          6818:  * htmlCtxtReadMemory:
        !          6819:  * @ctxt:  an HTML parser context
        !          6820:  * @buffer:  a pointer to a char array
        !          6821:  * @size:  the size of the array
        !          6822:  * @URL:  the base URL to use for the document
        !          6823:  * @encoding:  the document encoding, or NULL
        !          6824:  * @options:  a combination of htmlParserOption(s)
        !          6825:  *
        !          6826:  * parse an XML in-memory document and build a tree.
        !          6827:  * This reuses the existing @ctxt parser context
        !          6828:  *
        !          6829:  * Returns the resulting document tree
        !          6830:  */
        !          6831: htmlDocPtr
        !          6832: htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size,
        !          6833:                   const char *URL, const char *encoding, int options)
        !          6834: {
        !          6835:     xmlParserInputBufferPtr input;
        !          6836:     xmlParserInputPtr stream;
        !          6837: 
        !          6838:     if (ctxt == NULL)
        !          6839:         return (NULL);
        !          6840:     if (buffer == NULL)
        !          6841:         return (NULL);
        !          6842: 
        !          6843:     htmlCtxtReset(ctxt);
        !          6844: 
        !          6845:     input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
        !          6846:     if (input == NULL) {
        !          6847:        return(NULL);
        !          6848:     }
        !          6849: 
        !          6850:     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
        !          6851:     if (stream == NULL) {
        !          6852:        xmlFreeParserInputBuffer(input);
        !          6853:        return(NULL);
        !          6854:     }
        !          6855: 
        !          6856:     inputPush(ctxt, stream);
        !          6857:     return (htmlDoRead(ctxt, URL, encoding, options, 1));
        !          6858: }
        !          6859: 
        !          6860: /**
        !          6861:  * htmlCtxtReadFd:
        !          6862:  * @ctxt:  an HTML parser context
        !          6863:  * @fd:  an open file descriptor
        !          6864:  * @URL:  the base URL to use for the document
        !          6865:  * @encoding:  the document encoding, or NULL
        !          6866:  * @options:  a combination of htmlParserOption(s)
        !          6867:  *
        !          6868:  * parse an XML from a file descriptor and build a tree.
        !          6869:  * This reuses the existing @ctxt parser context
        !          6870:  *
        !          6871:  * Returns the resulting document tree
        !          6872:  */
        !          6873: htmlDocPtr
        !          6874: htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd,
        !          6875:               const char *URL, const char *encoding, int options)
        !          6876: {
        !          6877:     xmlParserInputBufferPtr input;
        !          6878:     xmlParserInputPtr stream;
        !          6879: 
        !          6880:     if (fd < 0)
        !          6881:         return (NULL);
        !          6882:     if (ctxt == NULL)
        !          6883:         return (NULL);
        !          6884: 
        !          6885:     htmlCtxtReset(ctxt);
        !          6886: 
        !          6887: 
        !          6888:     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
        !          6889:     if (input == NULL)
        !          6890:         return (NULL);
        !          6891:     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
        !          6892:     if (stream == NULL) {
        !          6893:         xmlFreeParserInputBuffer(input);
        !          6894:         return (NULL);
        !          6895:     }
        !          6896:     inputPush(ctxt, stream);
        !          6897:     return (htmlDoRead(ctxt, URL, encoding, options, 1));
        !          6898: }
        !          6899: 
        !          6900: /**
        !          6901:  * htmlCtxtReadIO:
        !          6902:  * @ctxt:  an HTML parser context
        !          6903:  * @ioread:  an I/O read function
        !          6904:  * @ioclose:  an I/O close function
        !          6905:  * @ioctx:  an I/O handler
        !          6906:  * @URL:  the base URL to use for the document
        !          6907:  * @encoding:  the document encoding, or NULL
        !          6908:  * @options:  a combination of htmlParserOption(s)
        !          6909:  *
        !          6910:  * parse an HTML document from I/O functions and source and build a tree.
        !          6911:  * This reuses the existing @ctxt parser context
        !          6912:  *
        !          6913:  * Returns the resulting document tree
        !          6914:  */
        !          6915: htmlDocPtr
        !          6916: htmlCtxtReadIO(htmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
        !          6917:               xmlInputCloseCallback ioclose, void *ioctx,
        !          6918:              const char *URL,
        !          6919:               const char *encoding, int options)
        !          6920: {
        !          6921:     xmlParserInputBufferPtr input;
        !          6922:     xmlParserInputPtr stream;
        !          6923: 
        !          6924:     if (ioread == NULL)
        !          6925:         return (NULL);
        !          6926:     if (ctxt == NULL)
        !          6927:         return (NULL);
        !          6928: 
        !          6929:     htmlCtxtReset(ctxt);
        !          6930: 
        !          6931:     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
        !          6932:                                          XML_CHAR_ENCODING_NONE);
        !          6933:     if (input == NULL)
        !          6934:         return (NULL);
        !          6935:     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
        !          6936:     if (stream == NULL) {
        !          6937:         xmlFreeParserInputBuffer(input);
        !          6938:         return (NULL);
        !          6939:     }
        !          6940:     inputPush(ctxt, stream);
        !          6941:     return (htmlDoRead(ctxt, URL, encoding, options, 1));
        !          6942: }
        !          6943: 
        !          6944: #define bottom_HTMLparser
        !          6945: #include "elfgcchack.h"
        !          6946: #endif /* LIBXML_HTML_ENABLED */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>