Annotation of embedaddon/expat/lib/xmltok_impl.c, revision 1.1

1.1     ! misho       1: /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
        !             2:    See the file COPYING for copying permission.
        !             3: */
        !             4: 
        !             5: /* This file is included! */
        !             6: #ifdef XML_TOK_IMPL_C
        !             7: 
        !             8: #ifndef IS_INVALID_CHAR
        !             9: #define IS_INVALID_CHAR(enc, ptr, n) (0)
        !            10: #endif
        !            11: 
        !            12: #define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
        !            13:     case BT_LEAD ## n: \
        !            14:       if (end - ptr < n) \
        !            15:         return XML_TOK_PARTIAL_CHAR; \
        !            16:       if (IS_INVALID_CHAR(enc, ptr, n)) { \
        !            17:         *(nextTokPtr) = (ptr); \
        !            18:         return XML_TOK_INVALID; \
        !            19:       } \
        !            20:       ptr += n; \
        !            21:       break;
        !            22: 
        !            23: #define INVALID_CASES(ptr, nextTokPtr) \
        !            24:   INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
        !            25:   INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
        !            26:   INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
        !            27:   case BT_NONXML: \
        !            28:   case BT_MALFORM: \
        !            29:   case BT_TRAIL: \
        !            30:     *(nextTokPtr) = (ptr); \
        !            31:     return XML_TOK_INVALID;
        !            32: 
        !            33: #define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
        !            34:    case BT_LEAD ## n: \
        !            35:      if (end - ptr < n) \
        !            36:        return XML_TOK_PARTIAL_CHAR; \
        !            37:      if (!IS_NAME_CHAR(enc, ptr, n)) { \
        !            38:        *nextTokPtr = ptr; \
        !            39:        return XML_TOK_INVALID; \
        !            40:      } \
        !            41:      ptr += n; \
        !            42:      break;
        !            43: 
        !            44: #define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
        !            45:   case BT_NONASCII: \
        !            46:     if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
        !            47:       *nextTokPtr = ptr; \
        !            48:       return XML_TOK_INVALID; \
        !            49:     } \
        !            50:   case BT_NMSTRT: \
        !            51:   case BT_HEX: \
        !            52:   case BT_DIGIT: \
        !            53:   case BT_NAME: \
        !            54:   case BT_MINUS: \
        !            55:     ptr += MINBPC(enc); \
        !            56:     break; \
        !            57:   CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
        !            58:   CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
        !            59:   CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
        !            60: 
        !            61: #define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
        !            62:    case BT_LEAD ## n: \
        !            63:      if (end - ptr < n) \
        !            64:        return XML_TOK_PARTIAL_CHAR; \
        !            65:      if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
        !            66:        *nextTokPtr = ptr; \
        !            67:        return XML_TOK_INVALID; \
        !            68:      } \
        !            69:      ptr += n; \
        !            70:      break;
        !            71: 
        !            72: #define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
        !            73:   case BT_NONASCII: \
        !            74:     if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
        !            75:       *nextTokPtr = ptr; \
        !            76:       return XML_TOK_INVALID; \
        !            77:     } \
        !            78:   case BT_NMSTRT: \
        !            79:   case BT_HEX: \
        !            80:     ptr += MINBPC(enc); \
        !            81:     break; \
        !            82:   CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
        !            83:   CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
        !            84:   CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
        !            85: 
        !            86: #ifndef PREFIX
        !            87: #define PREFIX(ident) ident
        !            88: #endif
        !            89: 
        !            90: /* ptr points to character following "<!-" */
        !            91: 
        !            92: static int PTRCALL
        !            93: PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
        !            94:                     const char *end, const char **nextTokPtr)
        !            95: {
        !            96:   if (ptr != end) {
        !            97:     if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
        !            98:       *nextTokPtr = ptr;
        !            99:       return XML_TOK_INVALID;
        !           100:     }
        !           101:     ptr += MINBPC(enc);
        !           102:     while (ptr != end) {
        !           103:       switch (BYTE_TYPE(enc, ptr)) {
        !           104:       INVALID_CASES(ptr, nextTokPtr)
        !           105:       case BT_MINUS:
        !           106:         if ((ptr += MINBPC(enc)) == end)
        !           107:           return XML_TOK_PARTIAL;
        !           108:         if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
        !           109:           if ((ptr += MINBPC(enc)) == end)
        !           110:             return XML_TOK_PARTIAL;
        !           111:           if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           112:             *nextTokPtr = ptr;
        !           113:             return XML_TOK_INVALID;
        !           114:           }
        !           115:           *nextTokPtr = ptr + MINBPC(enc);
        !           116:           return XML_TOK_COMMENT;
        !           117:         }
        !           118:         break;
        !           119:       default:
        !           120:         ptr += MINBPC(enc);
        !           121:         break;
        !           122:       }
        !           123:     }
        !           124:   }
        !           125:   return XML_TOK_PARTIAL;
        !           126: }
        !           127: 
        !           128: /* ptr points to character following "<!" */
        !           129: 
        !           130: static int PTRCALL
        !           131: PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
        !           132:                  const char *end, const char **nextTokPtr)
        !           133: {
        !           134:   if (ptr == end)
        !           135:     return XML_TOK_PARTIAL;
        !           136:   switch (BYTE_TYPE(enc, ptr)) {
        !           137:   case BT_MINUS:
        !           138:     return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           139:   case BT_LSQB:
        !           140:     *nextTokPtr = ptr + MINBPC(enc);
        !           141:     return XML_TOK_COND_SECT_OPEN;
        !           142:   case BT_NMSTRT:
        !           143:   case BT_HEX:
        !           144:     ptr += MINBPC(enc);
        !           145:     break;
        !           146:   default:
        !           147:     *nextTokPtr = ptr;
        !           148:     return XML_TOK_INVALID;
        !           149:   }
        !           150:   while (ptr != end) {
        !           151:     switch (BYTE_TYPE(enc, ptr)) {
        !           152:     case BT_PERCNT:
        !           153:       if (ptr + MINBPC(enc) == end)
        !           154:         return XML_TOK_PARTIAL;
        !           155:       /* don't allow <!ENTITY% foo "whatever"> */
        !           156:       switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
        !           157:       case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
        !           158:         *nextTokPtr = ptr;
        !           159:         return XML_TOK_INVALID;
        !           160:       }
        !           161:       /* fall through */
        !           162:     case BT_S: case BT_CR: case BT_LF:
        !           163:       *nextTokPtr = ptr;
        !           164:       return XML_TOK_DECL_OPEN;
        !           165:     case BT_NMSTRT:
        !           166:     case BT_HEX:
        !           167:       ptr += MINBPC(enc);
        !           168:       break;
        !           169:     default:
        !           170:       *nextTokPtr = ptr;
        !           171:       return XML_TOK_INVALID;
        !           172:     }
        !           173:   }
        !           174:   return XML_TOK_PARTIAL;
        !           175: }
        !           176: 
        !           177: static int PTRCALL
        !           178: PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr,
        !           179:                       const char *end, int *tokPtr)
        !           180: {
        !           181:   int upper = 0;
        !           182:   *tokPtr = XML_TOK_PI;
        !           183:   if (end - ptr != MINBPC(enc)*3)
        !           184:     return 1;
        !           185:   switch (BYTE_TO_ASCII(enc, ptr)) {
        !           186:   case ASCII_x:
        !           187:     break;
        !           188:   case ASCII_X:
        !           189:     upper = 1;
        !           190:     break;
        !           191:   default:
        !           192:     return 1;
        !           193:   }
        !           194:   ptr += MINBPC(enc);
        !           195:   switch (BYTE_TO_ASCII(enc, ptr)) {
        !           196:   case ASCII_m:
        !           197:     break;
        !           198:   case ASCII_M:
        !           199:     upper = 1;
        !           200:     break;
        !           201:   default:
        !           202:     return 1;
        !           203:   }
        !           204:   ptr += MINBPC(enc);
        !           205:   switch (BYTE_TO_ASCII(enc, ptr)) {
        !           206:   case ASCII_l:
        !           207:     break;
        !           208:   case ASCII_L:
        !           209:     upper = 1;
        !           210:     break;
        !           211:   default:
        !           212:     return 1;
        !           213:   }
        !           214:   if (upper)
        !           215:     return 0;
        !           216:   *tokPtr = XML_TOK_XML_DECL;
        !           217:   return 1;
        !           218: }
        !           219: 
        !           220: /* ptr points to character following "<?" */
        !           221: 
        !           222: static int PTRCALL
        !           223: PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
        !           224:                const char *end, const char **nextTokPtr)
        !           225: {
        !           226:   int tok;
        !           227:   const char *target = ptr;
        !           228:   if (ptr == end)
        !           229:     return XML_TOK_PARTIAL;
        !           230:   switch (BYTE_TYPE(enc, ptr)) {
        !           231:   CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           232:   default:
        !           233:     *nextTokPtr = ptr;
        !           234:     return XML_TOK_INVALID;
        !           235:   }
        !           236:   while (ptr != end) {
        !           237:     switch (BYTE_TYPE(enc, ptr)) {
        !           238:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           239:     case BT_S: case BT_CR: case BT_LF:
        !           240:       if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
        !           241:         *nextTokPtr = ptr;
        !           242:         return XML_TOK_INVALID;
        !           243:       }
        !           244:       ptr += MINBPC(enc);
        !           245:       while (ptr != end) {
        !           246:         switch (BYTE_TYPE(enc, ptr)) {
        !           247:         INVALID_CASES(ptr, nextTokPtr)
        !           248:         case BT_QUEST:
        !           249:           ptr += MINBPC(enc);
        !           250:           if (ptr == end)
        !           251:             return XML_TOK_PARTIAL;
        !           252:           if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           253:             *nextTokPtr = ptr + MINBPC(enc);
        !           254:             return tok;
        !           255:           }
        !           256:           break;
        !           257:         default:
        !           258:           ptr += MINBPC(enc);
        !           259:           break;
        !           260:         }
        !           261:       }
        !           262:       return XML_TOK_PARTIAL;
        !           263:     case BT_QUEST:
        !           264:       if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
        !           265:         *nextTokPtr = ptr;
        !           266:         return XML_TOK_INVALID;
        !           267:       }
        !           268:       ptr += MINBPC(enc);
        !           269:       if (ptr == end)
        !           270:         return XML_TOK_PARTIAL;
        !           271:       if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           272:         *nextTokPtr = ptr + MINBPC(enc);
        !           273:         return tok;
        !           274:       }
        !           275:       /* fall through */
        !           276:     default:
        !           277:       *nextTokPtr = ptr;
        !           278:       return XML_TOK_INVALID;
        !           279:     }
        !           280:   }
        !           281:   return XML_TOK_PARTIAL;
        !           282: }
        !           283: 
        !           284: static int PTRCALL
        !           285: PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr,
        !           286:                          const char *end, const char **nextTokPtr)
        !           287: {
        !           288:   static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A,
        !           289:                                      ASCII_T, ASCII_A, ASCII_LSQB };
        !           290:   int i;
        !           291:   /* CDATA[ */
        !           292:   if (end - ptr < 6 * MINBPC(enc))
        !           293:     return XML_TOK_PARTIAL;
        !           294:   for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
        !           295:     if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
        !           296:       *nextTokPtr = ptr;
        !           297:       return XML_TOK_INVALID;
        !           298:     }
        !           299:   }
        !           300:   *nextTokPtr = ptr;
        !           301:   return XML_TOK_CDATA_SECT_OPEN;
        !           302: }
        !           303: 
        !           304: static int PTRCALL
        !           305: PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
        !           306:                         const char *end, const char **nextTokPtr)
        !           307: {
        !           308:   if (ptr == end)
        !           309:     return XML_TOK_NONE;
        !           310:   if (MINBPC(enc) > 1) {
        !           311:     size_t n = end - ptr;
        !           312:     if (n & (MINBPC(enc) - 1)) {
        !           313:       n &= ~(MINBPC(enc) - 1);
        !           314:       if (n == 0)
        !           315:         return XML_TOK_PARTIAL;
        !           316:       end = ptr + n;
        !           317:     }
        !           318:   }
        !           319:   switch (BYTE_TYPE(enc, ptr)) {
        !           320:   case BT_RSQB:
        !           321:     ptr += MINBPC(enc);
        !           322:     if (ptr == end)
        !           323:       return XML_TOK_PARTIAL;
        !           324:     if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
        !           325:       break;
        !           326:     ptr += MINBPC(enc);
        !           327:     if (ptr == end)
        !           328:       return XML_TOK_PARTIAL;
        !           329:     if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           330:       ptr -= MINBPC(enc);
        !           331:       break;
        !           332:     }
        !           333:     *nextTokPtr = ptr + MINBPC(enc);
        !           334:     return XML_TOK_CDATA_SECT_CLOSE;
        !           335:   case BT_CR:
        !           336:     ptr += MINBPC(enc);
        !           337:     if (ptr == end)
        !           338:       return XML_TOK_PARTIAL;
        !           339:     if (BYTE_TYPE(enc, ptr) == BT_LF)
        !           340:       ptr += MINBPC(enc);
        !           341:     *nextTokPtr = ptr;
        !           342:     return XML_TOK_DATA_NEWLINE;
        !           343:   case BT_LF:
        !           344:     *nextTokPtr = ptr + MINBPC(enc);
        !           345:     return XML_TOK_DATA_NEWLINE;
        !           346:   INVALID_CASES(ptr, nextTokPtr)
        !           347:   default:
        !           348:     ptr += MINBPC(enc);
        !           349:     break;
        !           350:   }
        !           351:   while (ptr != end) {
        !           352:     switch (BYTE_TYPE(enc, ptr)) {
        !           353: #define LEAD_CASE(n) \
        !           354:     case BT_LEAD ## n: \
        !           355:       if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
        !           356:         *nextTokPtr = ptr; \
        !           357:         return XML_TOK_DATA_CHARS; \
        !           358:       } \
        !           359:       ptr += n; \
        !           360:       break;
        !           361:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !           362: #undef LEAD_CASE
        !           363:     case BT_NONXML:
        !           364:     case BT_MALFORM:
        !           365:     case BT_TRAIL:
        !           366:     case BT_CR:
        !           367:     case BT_LF:
        !           368:     case BT_RSQB:
        !           369:       *nextTokPtr = ptr;
        !           370:       return XML_TOK_DATA_CHARS;
        !           371:     default:
        !           372:       ptr += MINBPC(enc);
        !           373:       break;
        !           374:     }
        !           375:   }
        !           376:   *nextTokPtr = ptr;
        !           377:   return XML_TOK_DATA_CHARS;
        !           378: }
        !           379: 
        !           380: /* ptr points to character following "</" */
        !           381: 
        !           382: static int PTRCALL
        !           383: PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
        !           384:                    const char *end, const char **nextTokPtr)
        !           385: {
        !           386:   if (ptr == end)
        !           387:     return XML_TOK_PARTIAL;
        !           388:   switch (BYTE_TYPE(enc, ptr)) {
        !           389:   CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           390:   default:
        !           391:     *nextTokPtr = ptr;
        !           392:     return XML_TOK_INVALID;
        !           393:   }
        !           394:   while (ptr != end) {
        !           395:     switch (BYTE_TYPE(enc, ptr)) {
        !           396:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           397:     case BT_S: case BT_CR: case BT_LF:
        !           398:       for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
        !           399:         switch (BYTE_TYPE(enc, ptr)) {
        !           400:         case BT_S: case BT_CR: case BT_LF:
        !           401:           break;
        !           402:         case BT_GT:
        !           403:           *nextTokPtr = ptr + MINBPC(enc);
        !           404:           return XML_TOK_END_TAG;
        !           405:         default:
        !           406:           *nextTokPtr = ptr;
        !           407:           return XML_TOK_INVALID;
        !           408:         }
        !           409:       }
        !           410:       return XML_TOK_PARTIAL;
        !           411: #ifdef XML_NS
        !           412:     case BT_COLON:
        !           413:       /* no need to check qname syntax here,
        !           414:          since end-tag must match exactly */
        !           415:       ptr += MINBPC(enc);
        !           416:       break;
        !           417: #endif
        !           418:     case BT_GT:
        !           419:       *nextTokPtr = ptr + MINBPC(enc);
        !           420:       return XML_TOK_END_TAG;
        !           421:     default:
        !           422:       *nextTokPtr = ptr;
        !           423:       return XML_TOK_INVALID;
        !           424:     }
        !           425:   }
        !           426:   return XML_TOK_PARTIAL;
        !           427: }
        !           428: 
        !           429: /* ptr points to character following "&#X" */
        !           430: 
        !           431: static int PTRCALL
        !           432: PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
        !           433:                        const char *end, const char **nextTokPtr)
        !           434: {
        !           435:   if (ptr != end) {
        !           436:     switch (BYTE_TYPE(enc, ptr)) {
        !           437:     case BT_DIGIT:
        !           438:     case BT_HEX:
        !           439:       break;
        !           440:     default:
        !           441:       *nextTokPtr = ptr;
        !           442:       return XML_TOK_INVALID;
        !           443:     }
        !           444:     for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
        !           445:       switch (BYTE_TYPE(enc, ptr)) {
        !           446:       case BT_DIGIT:
        !           447:       case BT_HEX:
        !           448:         break;
        !           449:       case BT_SEMI:
        !           450:         *nextTokPtr = ptr + MINBPC(enc);
        !           451:         return XML_TOK_CHAR_REF;
        !           452:       default:
        !           453:         *nextTokPtr = ptr;
        !           454:         return XML_TOK_INVALID;
        !           455:       }
        !           456:     }
        !           457:   }
        !           458:   return XML_TOK_PARTIAL;
        !           459: }
        !           460: 
        !           461: /* ptr points to character following "&#" */
        !           462: 
        !           463: static int PTRCALL
        !           464: PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
        !           465:                     const char *end, const char **nextTokPtr)
        !           466: {
        !           467:   if (ptr != end) {
        !           468:     if (CHAR_MATCHES(enc, ptr, ASCII_x))
        !           469:       return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           470:     switch (BYTE_TYPE(enc, ptr)) {
        !           471:     case BT_DIGIT:
        !           472:       break;
        !           473:     default:
        !           474:       *nextTokPtr = ptr;
        !           475:       return XML_TOK_INVALID;
        !           476:     }
        !           477:     for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
        !           478:       switch (BYTE_TYPE(enc, ptr)) {
        !           479:       case BT_DIGIT:
        !           480:         break;
        !           481:       case BT_SEMI:
        !           482:         *nextTokPtr = ptr + MINBPC(enc);
        !           483:         return XML_TOK_CHAR_REF;
        !           484:       default:
        !           485:         *nextTokPtr = ptr;
        !           486:         return XML_TOK_INVALID;
        !           487:       }
        !           488:     }
        !           489:   }
        !           490:   return XML_TOK_PARTIAL;
        !           491: }
        !           492: 
        !           493: /* ptr points to character following "&" */
        !           494: 
        !           495: static int PTRCALL
        !           496: PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
        !           497:                 const char **nextTokPtr)
        !           498: {
        !           499:   if (ptr == end)
        !           500:     return XML_TOK_PARTIAL;
        !           501:   switch (BYTE_TYPE(enc, ptr)) {
        !           502:   CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           503:   case BT_NUM:
        !           504:     return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           505:   default:
        !           506:     *nextTokPtr = ptr;
        !           507:     return XML_TOK_INVALID;
        !           508:   }
        !           509:   while (ptr != end) {
        !           510:     switch (BYTE_TYPE(enc, ptr)) {
        !           511:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           512:     case BT_SEMI:
        !           513:       *nextTokPtr = ptr + MINBPC(enc);
        !           514:       return XML_TOK_ENTITY_REF;
        !           515:     default:
        !           516:       *nextTokPtr = ptr;
        !           517:       return XML_TOK_INVALID;
        !           518:     }
        !           519:   }
        !           520:   return XML_TOK_PARTIAL;
        !           521: }
        !           522: 
        !           523: /* ptr points to character following first character of attribute name */
        !           524: 
        !           525: static int PTRCALL
        !           526: PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
        !           527:                  const char **nextTokPtr)
        !           528: {
        !           529: #ifdef XML_NS
        !           530:   int hadColon = 0;
        !           531: #endif
        !           532:   while (ptr != end) {
        !           533:     switch (BYTE_TYPE(enc, ptr)) {
        !           534:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           535: #ifdef XML_NS
        !           536:     case BT_COLON:
        !           537:       if (hadColon) {
        !           538:         *nextTokPtr = ptr;
        !           539:         return XML_TOK_INVALID;
        !           540:       }
        !           541:       hadColon = 1;
        !           542:       ptr += MINBPC(enc);
        !           543:       if (ptr == end)
        !           544:         return XML_TOK_PARTIAL;
        !           545:       switch (BYTE_TYPE(enc, ptr)) {
        !           546:       CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           547:       default:
        !           548:         *nextTokPtr = ptr;
        !           549:         return XML_TOK_INVALID;
        !           550:       }
        !           551:       break;
        !           552: #endif
        !           553:     case BT_S: case BT_CR: case BT_LF:
        !           554:       for (;;) {
        !           555:         int t;
        !           556: 
        !           557:         ptr += MINBPC(enc);
        !           558:         if (ptr == end)
        !           559:           return XML_TOK_PARTIAL;
        !           560:         t = BYTE_TYPE(enc, ptr);
        !           561:         if (t == BT_EQUALS)
        !           562:           break;
        !           563:         switch (t) {
        !           564:         case BT_S:
        !           565:         case BT_LF:
        !           566:         case BT_CR:
        !           567:           break;
        !           568:         default:
        !           569:           *nextTokPtr = ptr;
        !           570:           return XML_TOK_INVALID;
        !           571:         }
        !           572:       }
        !           573:     /* fall through */
        !           574:     case BT_EQUALS:
        !           575:       {
        !           576:         int open;
        !           577: #ifdef XML_NS
        !           578:         hadColon = 0;
        !           579: #endif
        !           580:         for (;;) {
        !           581:           ptr += MINBPC(enc);
        !           582:           if (ptr == end)
        !           583:             return XML_TOK_PARTIAL;
        !           584:           open = BYTE_TYPE(enc, ptr);
        !           585:           if (open == BT_QUOT || open == BT_APOS)
        !           586:             break;
        !           587:           switch (open) {
        !           588:           case BT_S:
        !           589:           case BT_LF:
        !           590:           case BT_CR:
        !           591:             break;
        !           592:           default:
        !           593:             *nextTokPtr = ptr;
        !           594:             return XML_TOK_INVALID;
        !           595:           }
        !           596:         }
        !           597:         ptr += MINBPC(enc);
        !           598:         /* in attribute value */
        !           599:         for (;;) {
        !           600:           int t;
        !           601:           if (ptr == end)
        !           602:             return XML_TOK_PARTIAL;
        !           603:           t = BYTE_TYPE(enc, ptr);
        !           604:           if (t == open)
        !           605:             break;
        !           606:           switch (t) {
        !           607:           INVALID_CASES(ptr, nextTokPtr)
        !           608:           case BT_AMP:
        !           609:             {
        !           610:               int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
        !           611:               if (tok <= 0) {
        !           612:                 if (tok == XML_TOK_INVALID)
        !           613:                   *nextTokPtr = ptr;
        !           614:                 return tok;
        !           615:               }
        !           616:               break;
        !           617:             }
        !           618:           case BT_LT:
        !           619:             *nextTokPtr = ptr;
        !           620:             return XML_TOK_INVALID;
        !           621:           default:
        !           622:             ptr += MINBPC(enc);
        !           623:             break;
        !           624:           }
        !           625:         }
        !           626:         ptr += MINBPC(enc);
        !           627:         if (ptr == end)
        !           628:           return XML_TOK_PARTIAL;
        !           629:         switch (BYTE_TYPE(enc, ptr)) {
        !           630:         case BT_S:
        !           631:         case BT_CR:
        !           632:         case BT_LF:
        !           633:           break;
        !           634:         case BT_SOL:
        !           635:           goto sol;
        !           636:         case BT_GT:
        !           637:           goto gt;
        !           638:         default:
        !           639:           *nextTokPtr = ptr;
        !           640:           return XML_TOK_INVALID;
        !           641:         }
        !           642:         /* ptr points to closing quote */
        !           643:         for (;;) {
        !           644:           ptr += MINBPC(enc);
        !           645:           if (ptr == end)
        !           646:             return XML_TOK_PARTIAL;
        !           647:           switch (BYTE_TYPE(enc, ptr)) {
        !           648:           CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           649:           case BT_S: case BT_CR: case BT_LF:
        !           650:             continue;
        !           651:           case BT_GT:
        !           652:           gt:
        !           653:             *nextTokPtr = ptr + MINBPC(enc);
        !           654:             return XML_TOK_START_TAG_WITH_ATTS;
        !           655:           case BT_SOL:
        !           656:           sol:
        !           657:             ptr += MINBPC(enc);
        !           658:             if (ptr == end)
        !           659:               return XML_TOK_PARTIAL;
        !           660:             if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           661:               *nextTokPtr = ptr;
        !           662:               return XML_TOK_INVALID;
        !           663:             }
        !           664:             *nextTokPtr = ptr + MINBPC(enc);
        !           665:             return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
        !           666:           default:
        !           667:             *nextTokPtr = ptr;
        !           668:             return XML_TOK_INVALID;
        !           669:           }
        !           670:           break;
        !           671:         }
        !           672:         break;
        !           673:       }
        !           674:     default:
        !           675:       *nextTokPtr = ptr;
        !           676:       return XML_TOK_INVALID;
        !           677:     }
        !           678:   }
        !           679:   return XML_TOK_PARTIAL;
        !           680: }
        !           681: 
        !           682: /* ptr points to character following "<" */
        !           683: 
        !           684: static int PTRCALL
        !           685: PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
        !           686:                const char **nextTokPtr)
        !           687: {
        !           688: #ifdef XML_NS
        !           689:   int hadColon;
        !           690: #endif
        !           691:   if (ptr == end)
        !           692:     return XML_TOK_PARTIAL;
        !           693:   switch (BYTE_TYPE(enc, ptr)) {
        !           694:   CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           695:   case BT_EXCL:
        !           696:     if ((ptr += MINBPC(enc)) == end)
        !           697:       return XML_TOK_PARTIAL;
        !           698:     switch (BYTE_TYPE(enc, ptr)) {
        !           699:     case BT_MINUS:
        !           700:       return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           701:     case BT_LSQB:
        !           702:       return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc),
        !           703:                                       end, nextTokPtr);
        !           704:     }
        !           705:     *nextTokPtr = ptr;
        !           706:     return XML_TOK_INVALID;
        !           707:   case BT_QUEST:
        !           708:     return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           709:   case BT_SOL:
        !           710:     return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           711:   default:
        !           712:     *nextTokPtr = ptr;
        !           713:     return XML_TOK_INVALID;
        !           714:   }
        !           715: #ifdef XML_NS
        !           716:   hadColon = 0;
        !           717: #endif
        !           718:   /* we have a start-tag */
        !           719:   while (ptr != end) {
        !           720:     switch (BYTE_TYPE(enc, ptr)) {
        !           721:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           722: #ifdef XML_NS
        !           723:     case BT_COLON:
        !           724:       if (hadColon) {
        !           725:         *nextTokPtr = ptr;
        !           726:         return XML_TOK_INVALID;
        !           727:       }
        !           728:       hadColon = 1;
        !           729:       ptr += MINBPC(enc);
        !           730:       if (ptr == end)
        !           731:         return XML_TOK_PARTIAL;
        !           732:       switch (BYTE_TYPE(enc, ptr)) {
        !           733:       CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           734:       default:
        !           735:         *nextTokPtr = ptr;
        !           736:         return XML_TOK_INVALID;
        !           737:       }
        !           738:       break;
        !           739: #endif
        !           740:     case BT_S: case BT_CR: case BT_LF:
        !           741:       {
        !           742:         ptr += MINBPC(enc);
        !           743:         while (ptr != end) {
        !           744:           switch (BYTE_TYPE(enc, ptr)) {
        !           745:           CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           746:           case BT_GT:
        !           747:             goto gt;
        !           748:           case BT_SOL:
        !           749:             goto sol;
        !           750:           case BT_S: case BT_CR: case BT_LF:
        !           751:             ptr += MINBPC(enc);
        !           752:             continue;
        !           753:           default:
        !           754:             *nextTokPtr = ptr;
        !           755:             return XML_TOK_INVALID;
        !           756:           }
        !           757:           return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
        !           758:         }
        !           759:         return XML_TOK_PARTIAL;
        !           760:       }
        !           761:     case BT_GT:
        !           762:     gt:
        !           763:       *nextTokPtr = ptr + MINBPC(enc);
        !           764:       return XML_TOK_START_TAG_NO_ATTS;
        !           765:     case BT_SOL:
        !           766:     sol:
        !           767:       ptr += MINBPC(enc);
        !           768:       if (ptr == end)
        !           769:         return XML_TOK_PARTIAL;
        !           770:       if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           771:         *nextTokPtr = ptr;
        !           772:         return XML_TOK_INVALID;
        !           773:       }
        !           774:       *nextTokPtr = ptr + MINBPC(enc);
        !           775:       return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
        !           776:     default:
        !           777:       *nextTokPtr = ptr;
        !           778:       return XML_TOK_INVALID;
        !           779:     }
        !           780:   }
        !           781:   return XML_TOK_PARTIAL;
        !           782: }
        !           783: 
        !           784: static int PTRCALL
        !           785: PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
        !           786:                    const char **nextTokPtr)
        !           787: {
        !           788:   if (ptr == end)
        !           789:     return XML_TOK_NONE;
        !           790:   if (MINBPC(enc) > 1) {
        !           791:     size_t n = end - ptr;
        !           792:     if (n & (MINBPC(enc) - 1)) {
        !           793:       n &= ~(MINBPC(enc) - 1);
        !           794:       if (n == 0)
        !           795:         return XML_TOK_PARTIAL;
        !           796:       end = ptr + n;
        !           797:     }
        !           798:   }
        !           799:   switch (BYTE_TYPE(enc, ptr)) {
        !           800:   case BT_LT:
        !           801:     return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           802:   case BT_AMP:
        !           803:     return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           804:   case BT_CR:
        !           805:     ptr += MINBPC(enc);
        !           806:     if (ptr == end)
        !           807:       return XML_TOK_TRAILING_CR;
        !           808:     if (BYTE_TYPE(enc, ptr) == BT_LF)
        !           809:       ptr += MINBPC(enc);
        !           810:     *nextTokPtr = ptr;
        !           811:     return XML_TOK_DATA_NEWLINE;
        !           812:   case BT_LF:
        !           813:     *nextTokPtr = ptr + MINBPC(enc);
        !           814:     return XML_TOK_DATA_NEWLINE;
        !           815:   case BT_RSQB:
        !           816:     ptr += MINBPC(enc);
        !           817:     if (ptr == end)
        !           818:       return XML_TOK_TRAILING_RSQB;
        !           819:     if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
        !           820:       break;
        !           821:     ptr += MINBPC(enc);
        !           822:     if (ptr == end)
        !           823:       return XML_TOK_TRAILING_RSQB;
        !           824:     if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !           825:       ptr -= MINBPC(enc);
        !           826:       break;
        !           827:     }
        !           828:     *nextTokPtr = ptr;
        !           829:     return XML_TOK_INVALID;
        !           830:   INVALID_CASES(ptr, nextTokPtr)
        !           831:   default:
        !           832:     ptr += MINBPC(enc);
        !           833:     break;
        !           834:   }
        !           835:   while (ptr != end) {
        !           836:     switch (BYTE_TYPE(enc, ptr)) {
        !           837: #define LEAD_CASE(n) \
        !           838:     case BT_LEAD ## n: \
        !           839:       if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
        !           840:         *nextTokPtr = ptr; \
        !           841:         return XML_TOK_DATA_CHARS; \
        !           842:       } \
        !           843:       ptr += n; \
        !           844:       break;
        !           845:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !           846: #undef LEAD_CASE
        !           847:     case BT_RSQB:
        !           848:       if (ptr + MINBPC(enc) != end) {
        !           849:          if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
        !           850:            ptr += MINBPC(enc);
        !           851:            break;
        !           852:          }
        !           853:          if (ptr + 2*MINBPC(enc) != end) {
        !           854:            if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
        !           855:              ptr += MINBPC(enc);
        !           856:              break;
        !           857:            }
        !           858:            *nextTokPtr = ptr + 2*MINBPC(enc);
        !           859:            return XML_TOK_INVALID;
        !           860:          }
        !           861:       }
        !           862:       /* fall through */
        !           863:     case BT_AMP:
        !           864:     case BT_LT:
        !           865:     case BT_NONXML:
        !           866:     case BT_MALFORM:
        !           867:     case BT_TRAIL:
        !           868:     case BT_CR:
        !           869:     case BT_LF:
        !           870:       *nextTokPtr = ptr;
        !           871:       return XML_TOK_DATA_CHARS;
        !           872:     default:
        !           873:       ptr += MINBPC(enc);
        !           874:       break;
        !           875:     }
        !           876:   }
        !           877:   *nextTokPtr = ptr;
        !           878:   return XML_TOK_DATA_CHARS;
        !           879: }
        !           880: 
        !           881: /* ptr points to character following "%" */
        !           882: 
        !           883: static int PTRCALL
        !           884: PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
        !           885:                     const char **nextTokPtr)
        !           886: {
        !           887:   if (ptr == end)
        !           888:     return -XML_TOK_PERCENT;
        !           889:   switch (BYTE_TYPE(enc, ptr)) {
        !           890:   CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           891:   case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
        !           892:     *nextTokPtr = ptr;
        !           893:     return XML_TOK_PERCENT;
        !           894:   default:
        !           895:     *nextTokPtr = ptr;
        !           896:     return XML_TOK_INVALID;
        !           897:   }
        !           898:   while (ptr != end) {
        !           899:     switch (BYTE_TYPE(enc, ptr)) {
        !           900:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           901:     case BT_SEMI:
        !           902:       *nextTokPtr = ptr + MINBPC(enc);
        !           903:       return XML_TOK_PARAM_ENTITY_REF;
        !           904:     default:
        !           905:       *nextTokPtr = ptr;
        !           906:       return XML_TOK_INVALID;
        !           907:     }
        !           908:   }
        !           909:   return XML_TOK_PARTIAL;
        !           910: }
        !           911: 
        !           912: static int PTRCALL
        !           913: PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
        !           914:                       const char **nextTokPtr)
        !           915: {
        !           916:   if (ptr == end)
        !           917:     return XML_TOK_PARTIAL;
        !           918:   switch (BYTE_TYPE(enc, ptr)) {
        !           919:   CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
        !           920:   default:
        !           921:     *nextTokPtr = ptr;
        !           922:     return XML_TOK_INVALID;
        !           923:   }
        !           924:   while (ptr != end) {
        !           925:     switch (BYTE_TYPE(enc, ptr)) {
        !           926:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !           927:     case BT_CR: case BT_LF: case BT_S:
        !           928:     case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
        !           929:       *nextTokPtr = ptr;
        !           930:       return XML_TOK_POUND_NAME;
        !           931:     default:
        !           932:       *nextTokPtr = ptr;
        !           933:       return XML_TOK_INVALID;
        !           934:     }
        !           935:   }
        !           936:   return -XML_TOK_POUND_NAME;
        !           937: }
        !           938: 
        !           939: static int PTRCALL
        !           940: PREFIX(scanLit)(int open, const ENCODING *enc,
        !           941:                 const char *ptr, const char *end,
        !           942:                 const char **nextTokPtr)
        !           943: {
        !           944:   while (ptr != end) {
        !           945:     int t = BYTE_TYPE(enc, ptr);
        !           946:     switch (t) {
        !           947:     INVALID_CASES(ptr, nextTokPtr)
        !           948:     case BT_QUOT:
        !           949:     case BT_APOS:
        !           950:       ptr += MINBPC(enc);
        !           951:       if (t != open)
        !           952:         break;
        !           953:       if (ptr == end)
        !           954:         return -XML_TOK_LITERAL;
        !           955:       *nextTokPtr = ptr;
        !           956:       switch (BYTE_TYPE(enc, ptr)) {
        !           957:       case BT_S: case BT_CR: case BT_LF:
        !           958:       case BT_GT: case BT_PERCNT: case BT_LSQB:
        !           959:         return XML_TOK_LITERAL;
        !           960:       default:
        !           961:         return XML_TOK_INVALID;
        !           962:       }
        !           963:     default:
        !           964:       ptr += MINBPC(enc);
        !           965:       break;
        !           966:     }
        !           967:   }
        !           968:   return XML_TOK_PARTIAL;
        !           969: }
        !           970: 
        !           971: static int PTRCALL
        !           972: PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
        !           973:                   const char **nextTokPtr)
        !           974: {
        !           975:   int tok;
        !           976:   if (ptr == end)
        !           977:     return XML_TOK_NONE;
        !           978:   if (MINBPC(enc) > 1) {
        !           979:     size_t n = end - ptr;
        !           980:     if (n & (MINBPC(enc) - 1)) {
        !           981:       n &= ~(MINBPC(enc) - 1);
        !           982:       if (n == 0)
        !           983:         return XML_TOK_PARTIAL;
        !           984:       end = ptr + n;
        !           985:     }
        !           986:   }
        !           987:   switch (BYTE_TYPE(enc, ptr)) {
        !           988:   case BT_QUOT:
        !           989:     return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           990:   case BT_APOS:
        !           991:     return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
        !           992:   case BT_LT:
        !           993:     {
        !           994:       ptr += MINBPC(enc);
        !           995:       if (ptr == end)
        !           996:         return XML_TOK_PARTIAL;
        !           997:       switch (BYTE_TYPE(enc, ptr)) {
        !           998:       case BT_EXCL:
        !           999:         return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !          1000:       case BT_QUEST:
        !          1001:         return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !          1002:       case BT_NMSTRT:
        !          1003:       case BT_HEX:
        !          1004:       case BT_NONASCII:
        !          1005:       case BT_LEAD2:
        !          1006:       case BT_LEAD3:
        !          1007:       case BT_LEAD4:
        !          1008:         *nextTokPtr = ptr - MINBPC(enc);
        !          1009:         return XML_TOK_INSTANCE_START;
        !          1010:       }
        !          1011:       *nextTokPtr = ptr;
        !          1012:       return XML_TOK_INVALID;
        !          1013:     }
        !          1014:   case BT_CR:
        !          1015:     if (ptr + MINBPC(enc) == end) {
        !          1016:       *nextTokPtr = end;
        !          1017:       /* indicate that this might be part of a CR/LF pair */
        !          1018:       return -XML_TOK_PROLOG_S;
        !          1019:     }
        !          1020:     /* fall through */
        !          1021:   case BT_S: case BT_LF:
        !          1022:     for (;;) {
        !          1023:       ptr += MINBPC(enc);
        !          1024:       if (ptr == end)
        !          1025:         break;
        !          1026:       switch (BYTE_TYPE(enc, ptr)) {
        !          1027:       case BT_S: case BT_LF:
        !          1028:         break;
        !          1029:       case BT_CR:
        !          1030:         /* don't split CR/LF pair */
        !          1031:         if (ptr + MINBPC(enc) != end)
        !          1032:           break;
        !          1033:         /* fall through */
        !          1034:       default:
        !          1035:         *nextTokPtr = ptr;
        !          1036:         return XML_TOK_PROLOG_S;
        !          1037:       }
        !          1038:     }
        !          1039:     *nextTokPtr = ptr;
        !          1040:     return XML_TOK_PROLOG_S;
        !          1041:   case BT_PERCNT:
        !          1042:     return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !          1043:   case BT_COMMA:
        !          1044:     *nextTokPtr = ptr + MINBPC(enc);
        !          1045:     return XML_TOK_COMMA;
        !          1046:   case BT_LSQB:
        !          1047:     *nextTokPtr = ptr + MINBPC(enc);
        !          1048:     return XML_TOK_OPEN_BRACKET;
        !          1049:   case BT_RSQB:
        !          1050:     ptr += MINBPC(enc);
        !          1051:     if (ptr == end)
        !          1052:       return -XML_TOK_CLOSE_BRACKET;
        !          1053:     if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
        !          1054:       if (ptr + MINBPC(enc) == end)
        !          1055:         return XML_TOK_PARTIAL;
        !          1056:       if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
        !          1057:         *nextTokPtr = ptr + 2*MINBPC(enc);
        !          1058:         return XML_TOK_COND_SECT_CLOSE;
        !          1059:       }
        !          1060:     }
        !          1061:     *nextTokPtr = ptr;
        !          1062:     return XML_TOK_CLOSE_BRACKET;
        !          1063:   case BT_LPAR:
        !          1064:     *nextTokPtr = ptr + MINBPC(enc);
        !          1065:     return XML_TOK_OPEN_PAREN;
        !          1066:   case BT_RPAR:
        !          1067:     ptr += MINBPC(enc);
        !          1068:     if (ptr == end)
        !          1069:       return -XML_TOK_CLOSE_PAREN;
        !          1070:     switch (BYTE_TYPE(enc, ptr)) {
        !          1071:     case BT_AST:
        !          1072:       *nextTokPtr = ptr + MINBPC(enc);
        !          1073:       return XML_TOK_CLOSE_PAREN_ASTERISK;
        !          1074:     case BT_QUEST:
        !          1075:       *nextTokPtr = ptr + MINBPC(enc);
        !          1076:       return XML_TOK_CLOSE_PAREN_QUESTION;
        !          1077:     case BT_PLUS:
        !          1078:       *nextTokPtr = ptr + MINBPC(enc);
        !          1079:       return XML_TOK_CLOSE_PAREN_PLUS;
        !          1080:     case BT_CR: case BT_LF: case BT_S:
        !          1081:     case BT_GT: case BT_COMMA: case BT_VERBAR:
        !          1082:     case BT_RPAR:
        !          1083:       *nextTokPtr = ptr;
        !          1084:       return XML_TOK_CLOSE_PAREN;
        !          1085:     }
        !          1086:     *nextTokPtr = ptr;
        !          1087:     return XML_TOK_INVALID;
        !          1088:   case BT_VERBAR:
        !          1089:     *nextTokPtr = ptr + MINBPC(enc);
        !          1090:     return XML_TOK_OR;
        !          1091:   case BT_GT:
        !          1092:     *nextTokPtr = ptr + MINBPC(enc);
        !          1093:     return XML_TOK_DECL_CLOSE;
        !          1094:   case BT_NUM:
        !          1095:     return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !          1096: #define LEAD_CASE(n) \
        !          1097:   case BT_LEAD ## n: \
        !          1098:     if (end - ptr < n) \
        !          1099:       return XML_TOK_PARTIAL_CHAR; \
        !          1100:     if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
        !          1101:       ptr += n; \
        !          1102:       tok = XML_TOK_NAME; \
        !          1103:       break; \
        !          1104:     } \
        !          1105:     if (IS_NAME_CHAR(enc, ptr, n)) { \
        !          1106:       ptr += n; \
        !          1107:       tok = XML_TOK_NMTOKEN; \
        !          1108:       break; \
        !          1109:     } \
        !          1110:     *nextTokPtr = ptr; \
        !          1111:     return XML_TOK_INVALID;
        !          1112:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !          1113: #undef LEAD_CASE
        !          1114:   case BT_NMSTRT:
        !          1115:   case BT_HEX:
        !          1116:     tok = XML_TOK_NAME;
        !          1117:     ptr += MINBPC(enc);
        !          1118:     break;
        !          1119:   case BT_DIGIT:
        !          1120:   case BT_NAME:
        !          1121:   case BT_MINUS:
        !          1122: #ifdef XML_NS
        !          1123:   case BT_COLON:
        !          1124: #endif
        !          1125:     tok = XML_TOK_NMTOKEN;
        !          1126:     ptr += MINBPC(enc);
        !          1127:     break;
        !          1128:   case BT_NONASCII:
        !          1129:     if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
        !          1130:       ptr += MINBPC(enc);
        !          1131:       tok = XML_TOK_NAME;
        !          1132:       break;
        !          1133:     }
        !          1134:     if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
        !          1135:       ptr += MINBPC(enc);
        !          1136:       tok = XML_TOK_NMTOKEN;
        !          1137:       break;
        !          1138:     }
        !          1139:     /* fall through */
        !          1140:   default:
        !          1141:     *nextTokPtr = ptr;
        !          1142:     return XML_TOK_INVALID;
        !          1143:   }
        !          1144:   while (ptr != end) {
        !          1145:     switch (BYTE_TYPE(enc, ptr)) {
        !          1146:     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !          1147:     case BT_GT: case BT_RPAR: case BT_COMMA:
        !          1148:     case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
        !          1149:     case BT_S: case BT_CR: case BT_LF:
        !          1150:       *nextTokPtr = ptr;
        !          1151:       return tok;
        !          1152: #ifdef XML_NS
        !          1153:     case BT_COLON:
        !          1154:       ptr += MINBPC(enc);
        !          1155:       switch (tok) {
        !          1156:       case XML_TOK_NAME:
        !          1157:         if (ptr == end)
        !          1158:           return XML_TOK_PARTIAL;
        !          1159:         tok = XML_TOK_PREFIXED_NAME;
        !          1160:         switch (BYTE_TYPE(enc, ptr)) {
        !          1161:         CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
        !          1162:         default:
        !          1163:           tok = XML_TOK_NMTOKEN;
        !          1164:           break;
        !          1165:         }
        !          1166:         break;
        !          1167:       case XML_TOK_PREFIXED_NAME:
        !          1168:         tok = XML_TOK_NMTOKEN;
        !          1169:         break;
        !          1170:       }
        !          1171:       break;
        !          1172: #endif
        !          1173:     case BT_PLUS:
        !          1174:       if (tok == XML_TOK_NMTOKEN)  {
        !          1175:         *nextTokPtr = ptr;
        !          1176:         return XML_TOK_INVALID;
        !          1177:       }
        !          1178:       *nextTokPtr = ptr + MINBPC(enc);
        !          1179:       return XML_TOK_NAME_PLUS;
        !          1180:     case BT_AST:
        !          1181:       if (tok == XML_TOK_NMTOKEN)  {
        !          1182:         *nextTokPtr = ptr;
        !          1183:         return XML_TOK_INVALID;
        !          1184:       }
        !          1185:       *nextTokPtr = ptr + MINBPC(enc);
        !          1186:       return XML_TOK_NAME_ASTERISK;
        !          1187:     case BT_QUEST:
        !          1188:       if (tok == XML_TOK_NMTOKEN)  {
        !          1189:         *nextTokPtr = ptr;
        !          1190:         return XML_TOK_INVALID;
        !          1191:       }
        !          1192:       *nextTokPtr = ptr + MINBPC(enc);
        !          1193:       return XML_TOK_NAME_QUESTION;
        !          1194:     default:
        !          1195:       *nextTokPtr = ptr;
        !          1196:       return XML_TOK_INVALID;
        !          1197:     }
        !          1198:   }
        !          1199:   return -tok;
        !          1200: }
        !          1201: 
        !          1202: static int PTRCALL
        !          1203: PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
        !          1204:                           const char *end, const char **nextTokPtr)
        !          1205: {
        !          1206:   const char *start;
        !          1207:   if (ptr == end)
        !          1208:     return XML_TOK_NONE;
        !          1209:   start = ptr;
        !          1210:   while (ptr != end) {
        !          1211:     switch (BYTE_TYPE(enc, ptr)) {
        !          1212: #define LEAD_CASE(n) \
        !          1213:     case BT_LEAD ## n: ptr += n; break;
        !          1214:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !          1215: #undef LEAD_CASE
        !          1216:     case BT_AMP:
        !          1217:       if (ptr == start)
        !          1218:         return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !          1219:       *nextTokPtr = ptr;
        !          1220:       return XML_TOK_DATA_CHARS;
        !          1221:     case BT_LT:
        !          1222:       /* this is for inside entity references */
        !          1223:       *nextTokPtr = ptr;
        !          1224:       return XML_TOK_INVALID;
        !          1225:     case BT_LF:
        !          1226:       if (ptr == start) {
        !          1227:         *nextTokPtr = ptr + MINBPC(enc);
        !          1228:         return XML_TOK_DATA_NEWLINE;
        !          1229:       }
        !          1230:       *nextTokPtr = ptr;
        !          1231:       return XML_TOK_DATA_CHARS;
        !          1232:     case BT_CR:
        !          1233:       if (ptr == start) {
        !          1234:         ptr += MINBPC(enc);
        !          1235:         if (ptr == end)
        !          1236:           return XML_TOK_TRAILING_CR;
        !          1237:         if (BYTE_TYPE(enc, ptr) == BT_LF)
        !          1238:           ptr += MINBPC(enc);
        !          1239:         *nextTokPtr = ptr;
        !          1240:         return XML_TOK_DATA_NEWLINE;
        !          1241:       }
        !          1242:       *nextTokPtr = ptr;
        !          1243:       return XML_TOK_DATA_CHARS;
        !          1244:     case BT_S:
        !          1245:       if (ptr == start) {
        !          1246:         *nextTokPtr = ptr + MINBPC(enc);
        !          1247:         return XML_TOK_ATTRIBUTE_VALUE_S;
        !          1248:       }
        !          1249:       *nextTokPtr = ptr;
        !          1250:       return XML_TOK_DATA_CHARS;
        !          1251:     default:
        !          1252:       ptr += MINBPC(enc);
        !          1253:       break;
        !          1254:     }
        !          1255:   }
        !          1256:   *nextTokPtr = ptr;
        !          1257:   return XML_TOK_DATA_CHARS;
        !          1258: }
        !          1259: 
        !          1260: static int PTRCALL
        !          1261: PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
        !          1262:                        const char *end, const char **nextTokPtr)
        !          1263: {
        !          1264:   const char *start;
        !          1265:   if (ptr == end)
        !          1266:     return XML_TOK_NONE;
        !          1267:   start = ptr;
        !          1268:   while (ptr != end) {
        !          1269:     switch (BYTE_TYPE(enc, ptr)) {
        !          1270: #define LEAD_CASE(n) \
        !          1271:     case BT_LEAD ## n: ptr += n; break;
        !          1272:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !          1273: #undef LEAD_CASE
        !          1274:     case BT_AMP:
        !          1275:       if (ptr == start)
        !          1276:         return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
        !          1277:       *nextTokPtr = ptr;
        !          1278:       return XML_TOK_DATA_CHARS;
        !          1279:     case BT_PERCNT:
        !          1280:       if (ptr == start) {
        !          1281:         int tok =  PREFIX(scanPercent)(enc, ptr + MINBPC(enc),
        !          1282:                                        end, nextTokPtr);
        !          1283:         return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok;
        !          1284:       }
        !          1285:       *nextTokPtr = ptr;
        !          1286:       return XML_TOK_DATA_CHARS;
        !          1287:     case BT_LF:
        !          1288:       if (ptr == start) {
        !          1289:         *nextTokPtr = ptr + MINBPC(enc);
        !          1290:         return XML_TOK_DATA_NEWLINE;
        !          1291:       }
        !          1292:       *nextTokPtr = ptr;
        !          1293:       return XML_TOK_DATA_CHARS;
        !          1294:     case BT_CR:
        !          1295:       if (ptr == start) {
        !          1296:         ptr += MINBPC(enc);
        !          1297:         if (ptr == end)
        !          1298:           return XML_TOK_TRAILING_CR;
        !          1299:         if (BYTE_TYPE(enc, ptr) == BT_LF)
        !          1300:           ptr += MINBPC(enc);
        !          1301:         *nextTokPtr = ptr;
        !          1302:         return XML_TOK_DATA_NEWLINE;
        !          1303:       }
        !          1304:       *nextTokPtr = ptr;
        !          1305:       return XML_TOK_DATA_CHARS;
        !          1306:     default:
        !          1307:       ptr += MINBPC(enc);
        !          1308:       break;
        !          1309:     }
        !          1310:   }
        !          1311:   *nextTokPtr = ptr;
        !          1312:   return XML_TOK_DATA_CHARS;
        !          1313: }
        !          1314: 
        !          1315: #ifdef XML_DTD
        !          1316: 
        !          1317: static int PTRCALL
        !          1318: PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr,
        !          1319:                          const char *end, const char **nextTokPtr)
        !          1320: {
        !          1321:   int level = 0;
        !          1322:   if (MINBPC(enc) > 1) {
        !          1323:     size_t n = end - ptr;
        !          1324:     if (n & (MINBPC(enc) - 1)) {
        !          1325:       n &= ~(MINBPC(enc) - 1);
        !          1326:       end = ptr + n;
        !          1327:     }
        !          1328:   }
        !          1329:   while (ptr != end) {
        !          1330:     switch (BYTE_TYPE(enc, ptr)) {
        !          1331:     INVALID_CASES(ptr, nextTokPtr)
        !          1332:     case BT_LT:
        !          1333:       if ((ptr += MINBPC(enc)) == end)
        !          1334:         return XML_TOK_PARTIAL;
        !          1335:       if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) {
        !          1336:         if ((ptr += MINBPC(enc)) == end)
        !          1337:           return XML_TOK_PARTIAL;
        !          1338:         if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) {
        !          1339:           ++level;
        !          1340:           ptr += MINBPC(enc);
        !          1341:         }
        !          1342:       }
        !          1343:       break;
        !          1344:     case BT_RSQB:
        !          1345:       if ((ptr += MINBPC(enc)) == end)
        !          1346:         return XML_TOK_PARTIAL;
        !          1347:       if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
        !          1348:         if ((ptr += MINBPC(enc)) == end)
        !          1349:           return XML_TOK_PARTIAL;
        !          1350:         if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
        !          1351:           ptr += MINBPC(enc);
        !          1352:           if (level == 0) {
        !          1353:             *nextTokPtr = ptr;
        !          1354:             return XML_TOK_IGNORE_SECT;
        !          1355:           }
        !          1356:           --level;
        !          1357:         }
        !          1358:       }
        !          1359:       break;
        !          1360:     default:
        !          1361:       ptr += MINBPC(enc);
        !          1362:       break;
        !          1363:     }
        !          1364:   }
        !          1365:   return XML_TOK_PARTIAL;
        !          1366: }
        !          1367: 
        !          1368: #endif /* XML_DTD */
        !          1369: 
        !          1370: static int PTRCALL
        !          1371: PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
        !          1372:                    const char **badPtr)
        !          1373: {
        !          1374:   ptr += MINBPC(enc);
        !          1375:   end -= MINBPC(enc);
        !          1376:   for (; ptr != end; ptr += MINBPC(enc)) {
        !          1377:     switch (BYTE_TYPE(enc, ptr)) {
        !          1378:     case BT_DIGIT:
        !          1379:     case BT_HEX:
        !          1380:     case BT_MINUS:
        !          1381:     case BT_APOS:
        !          1382:     case BT_LPAR:
        !          1383:     case BT_RPAR:
        !          1384:     case BT_PLUS:
        !          1385:     case BT_COMMA:
        !          1386:     case BT_SOL:
        !          1387:     case BT_EQUALS:
        !          1388:     case BT_QUEST:
        !          1389:     case BT_CR:
        !          1390:     case BT_LF:
        !          1391:     case BT_SEMI:
        !          1392:     case BT_EXCL:
        !          1393:     case BT_AST:
        !          1394:     case BT_PERCNT:
        !          1395:     case BT_NUM:
        !          1396: #ifdef XML_NS
        !          1397:     case BT_COLON:
        !          1398: #endif
        !          1399:       break;
        !          1400:     case BT_S:
        !          1401:       if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
        !          1402:         *badPtr = ptr;
        !          1403:         return 0;
        !          1404:       }
        !          1405:       break;
        !          1406:     case BT_NAME:
        !          1407:     case BT_NMSTRT:
        !          1408:       if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
        !          1409:         break;
        !          1410:     default:
        !          1411:       switch (BYTE_TO_ASCII(enc, ptr)) {
        !          1412:       case 0x24: /* $ */
        !          1413:       case 0x40: /* @ */
        !          1414:         break;
        !          1415:       default:
        !          1416:         *badPtr = ptr;
        !          1417:         return 0;
        !          1418:       }
        !          1419:       break;
        !          1420:     }
        !          1421:   }
        !          1422:   return 1;
        !          1423: }
        !          1424: 
        !          1425: /* This must only be called for a well-formed start-tag or empty
        !          1426:    element tag.  Returns the number of attributes.  Pointers to the
        !          1427:    first attsMax attributes are stored in atts.
        !          1428: */
        !          1429: 
        !          1430: static int PTRCALL
        !          1431: PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
        !          1432:                 int attsMax, ATTRIBUTE *atts)
        !          1433: {
        !          1434:   enum { other, inName, inValue } state = inName;
        !          1435:   int nAtts = 0;
        !          1436:   int open = 0; /* defined when state == inValue;
        !          1437:                    initialization just to shut up compilers */
        !          1438: 
        !          1439:   for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
        !          1440:     switch (BYTE_TYPE(enc, ptr)) {
        !          1441: #define START_NAME \
        !          1442:       if (state == other) { \
        !          1443:         if (nAtts < attsMax) { \
        !          1444:           atts[nAtts].name = ptr; \
        !          1445:           atts[nAtts].normalized = 1; \
        !          1446:         } \
        !          1447:         state = inName; \
        !          1448:       }
        !          1449: #define LEAD_CASE(n) \
        !          1450:     case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
        !          1451:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !          1452: #undef LEAD_CASE
        !          1453:     case BT_NONASCII:
        !          1454:     case BT_NMSTRT:
        !          1455:     case BT_HEX:
        !          1456:       START_NAME
        !          1457:       break;
        !          1458: #undef START_NAME
        !          1459:     case BT_QUOT:
        !          1460:       if (state != inValue) {
        !          1461:         if (nAtts < attsMax)
        !          1462:           atts[nAtts].valuePtr = ptr + MINBPC(enc);
        !          1463:         state = inValue;
        !          1464:         open = BT_QUOT;
        !          1465:       }
        !          1466:       else if (open == BT_QUOT) {
        !          1467:         state = other;
        !          1468:         if (nAtts < attsMax)
        !          1469:           atts[nAtts].valueEnd = ptr;
        !          1470:         nAtts++;
        !          1471:       }
        !          1472:       break;
        !          1473:     case BT_APOS:
        !          1474:       if (state != inValue) {
        !          1475:         if (nAtts < attsMax)
        !          1476:           atts[nAtts].valuePtr = ptr + MINBPC(enc);
        !          1477:         state = inValue;
        !          1478:         open = BT_APOS;
        !          1479:       }
        !          1480:       else if (open == BT_APOS) {
        !          1481:         state = other;
        !          1482:         if (nAtts < attsMax)
        !          1483:           atts[nAtts].valueEnd = ptr;
        !          1484:         nAtts++;
        !          1485:       }
        !          1486:       break;
        !          1487:     case BT_AMP:
        !          1488:       if (nAtts < attsMax)
        !          1489:         atts[nAtts].normalized = 0;
        !          1490:       break;
        !          1491:     case BT_S:
        !          1492:       if (state == inName)
        !          1493:         state = other;
        !          1494:       else if (state == inValue
        !          1495:                && nAtts < attsMax
        !          1496:                && atts[nAtts].normalized
        !          1497:                && (ptr == atts[nAtts].valuePtr
        !          1498:                    || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
        !          1499:                    || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
        !          1500:                    || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
        !          1501:         atts[nAtts].normalized = 0;
        !          1502:       break;
        !          1503:     case BT_CR: case BT_LF:
        !          1504:       /* This case ensures that the first attribute name is counted
        !          1505:          Apart from that we could just change state on the quote. */
        !          1506:       if (state == inName)
        !          1507:         state = other;
        !          1508:       else if (state == inValue && nAtts < attsMax)
        !          1509:         atts[nAtts].normalized = 0;
        !          1510:       break;
        !          1511:     case BT_GT:
        !          1512:     case BT_SOL:
        !          1513:       if (state != inValue)
        !          1514:         return nAtts;
        !          1515:       break;
        !          1516:     default:
        !          1517:       break;
        !          1518:     }
        !          1519:   }
        !          1520:   /* not reached */
        !          1521: }
        !          1522: 
        !          1523: static int PTRFASTCALL
        !          1524: PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
        !          1525: {
        !          1526:   int result = 0;
        !          1527:   /* skip &# */
        !          1528:   ptr += 2*MINBPC(enc);
        !          1529:   if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
        !          1530:     for (ptr += MINBPC(enc);
        !          1531:          !CHAR_MATCHES(enc, ptr, ASCII_SEMI);
        !          1532:          ptr += MINBPC(enc)) {
        !          1533:       int c = BYTE_TO_ASCII(enc, ptr);
        !          1534:       switch (c) {
        !          1535:       case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
        !          1536:       case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
        !          1537:         result <<= 4;
        !          1538:         result |= (c - ASCII_0);
        !          1539:         break;
        !          1540:       case ASCII_A: case ASCII_B: case ASCII_C:
        !          1541:       case ASCII_D: case ASCII_E: case ASCII_F:
        !          1542:         result <<= 4;
        !          1543:         result += 10 + (c - ASCII_A);
        !          1544:         break;
        !          1545:       case ASCII_a: case ASCII_b: case ASCII_c:
        !          1546:       case ASCII_d: case ASCII_e: case ASCII_f:
        !          1547:         result <<= 4;
        !          1548:         result += 10 + (c - ASCII_a);
        !          1549:         break;
        !          1550:       }
        !          1551:       if (result >= 0x110000)
        !          1552:         return -1;
        !          1553:     }
        !          1554:   }
        !          1555:   else {
        !          1556:     for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
        !          1557:       int c = BYTE_TO_ASCII(enc, ptr);
        !          1558:       result *= 10;
        !          1559:       result += (c - ASCII_0);
        !          1560:       if (result >= 0x110000)
        !          1561:         return -1;
        !          1562:     }
        !          1563:   }
        !          1564:   return checkCharRefNumber(result);
        !          1565: }
        !          1566: 
        !          1567: static int PTRCALL
        !          1568: PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
        !          1569:                              const char *end)
        !          1570: {
        !          1571:   switch ((end - ptr)/MINBPC(enc)) {
        !          1572:   case 2:
        !          1573:     if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
        !          1574:       switch (BYTE_TO_ASCII(enc, ptr)) {
        !          1575:       case ASCII_l:
        !          1576:         return ASCII_LT;
        !          1577:       case ASCII_g:
        !          1578:         return ASCII_GT;
        !          1579:       }
        !          1580:     }
        !          1581:     break;
        !          1582:   case 3:
        !          1583:     if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
        !          1584:       ptr += MINBPC(enc);
        !          1585:       if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
        !          1586:         ptr += MINBPC(enc);
        !          1587:         if (CHAR_MATCHES(enc, ptr, ASCII_p))
        !          1588:           return ASCII_AMP;
        !          1589:       }
        !          1590:     }
        !          1591:     break;
        !          1592:   case 4:
        !          1593:     switch (BYTE_TO_ASCII(enc, ptr)) {
        !          1594:     case ASCII_q:
        !          1595:       ptr += MINBPC(enc);
        !          1596:       if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
        !          1597:         ptr += MINBPC(enc);
        !          1598:         if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
        !          1599:           ptr += MINBPC(enc);
        !          1600:           if (CHAR_MATCHES(enc, ptr, ASCII_t))
        !          1601:             return ASCII_QUOT;
        !          1602:         }
        !          1603:       }
        !          1604:       break;
        !          1605:     case ASCII_a:
        !          1606:       ptr += MINBPC(enc);
        !          1607:       if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
        !          1608:         ptr += MINBPC(enc);
        !          1609:         if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
        !          1610:           ptr += MINBPC(enc);
        !          1611:           if (CHAR_MATCHES(enc, ptr, ASCII_s))
        !          1612:             return ASCII_APOS;
        !          1613:         }
        !          1614:       }
        !          1615:       break;
        !          1616:     }
        !          1617:   }
        !          1618:   return 0;
        !          1619: }
        !          1620: 
        !          1621: static int PTRCALL
        !          1622: PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
        !          1623: {
        !          1624:   for (;;) {
        !          1625:     switch (BYTE_TYPE(enc, ptr1)) {
        !          1626: #define LEAD_CASE(n) \
        !          1627:     case BT_LEAD ## n: \
        !          1628:       if (*ptr1++ != *ptr2++) \
        !          1629:         return 0;
        !          1630:     LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
        !          1631: #undef LEAD_CASE
        !          1632:       /* fall through */
        !          1633:       if (*ptr1++ != *ptr2++)
        !          1634:         return 0;
        !          1635:       break;
        !          1636:     case BT_NONASCII:
        !          1637:     case BT_NMSTRT:
        !          1638: #ifdef XML_NS
        !          1639:     case BT_COLON:
        !          1640: #endif
        !          1641:     case BT_HEX:
        !          1642:     case BT_DIGIT:
        !          1643:     case BT_NAME:
        !          1644:     case BT_MINUS:
        !          1645:       if (*ptr2++ != *ptr1++)
        !          1646:         return 0;
        !          1647:       if (MINBPC(enc) > 1) {
        !          1648:         if (*ptr2++ != *ptr1++)
        !          1649:           return 0;
        !          1650:         if (MINBPC(enc) > 2) {
        !          1651:           if (*ptr2++ != *ptr1++)
        !          1652:             return 0;
        !          1653:           if (MINBPC(enc) > 3) {
        !          1654:             if (*ptr2++ != *ptr1++)
        !          1655:               return 0;
        !          1656:           }
        !          1657:         }
        !          1658:       }
        !          1659:       break;
        !          1660:     default:
        !          1661:       if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
        !          1662:         return 1;
        !          1663:       switch (BYTE_TYPE(enc, ptr2)) {
        !          1664:       case BT_LEAD2:
        !          1665:       case BT_LEAD3:
        !          1666:       case BT_LEAD4:
        !          1667:       case BT_NONASCII:
        !          1668:       case BT_NMSTRT:
        !          1669: #ifdef XML_NS
        !          1670:       case BT_COLON:
        !          1671: #endif
        !          1672:       case BT_HEX:
        !          1673:       case BT_DIGIT:
        !          1674:       case BT_NAME:
        !          1675:       case BT_MINUS:
        !          1676:         return 0;
        !          1677:       default:
        !          1678:         return 1;
        !          1679:       }
        !          1680:     }
        !          1681:   }
        !          1682:   /* not reached */
        !          1683: }
        !          1684: 
        !          1685: static int PTRCALL
        !          1686: PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
        !          1687:                          const char *end1, const char *ptr2)
        !          1688: {
        !          1689:   for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
        !          1690:     if (ptr1 == end1)
        !          1691:       return 0;
        !          1692:     if (!CHAR_MATCHES(enc, ptr1, *ptr2))
        !          1693:       return 0;
        !          1694:   }
        !          1695:   return ptr1 == end1;
        !          1696: }
        !          1697: 
        !          1698: static int PTRFASTCALL
        !          1699: PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
        !          1700: {
        !          1701:   const char *start = ptr;
        !          1702:   for (;;) {
        !          1703:     switch (BYTE_TYPE(enc, ptr)) {
        !          1704: #define LEAD_CASE(n) \
        !          1705:     case BT_LEAD ## n: ptr += n; break;
        !          1706:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !          1707: #undef LEAD_CASE
        !          1708:     case BT_NONASCII:
        !          1709:     case BT_NMSTRT:
        !          1710: #ifdef XML_NS
        !          1711:     case BT_COLON:
        !          1712: #endif
        !          1713:     case BT_HEX:
        !          1714:     case BT_DIGIT:
        !          1715:     case BT_NAME:
        !          1716:     case BT_MINUS:
        !          1717:       ptr += MINBPC(enc);
        !          1718:       break;
        !          1719:     default:
        !          1720:       return (int)(ptr - start);
        !          1721:     }
        !          1722:   }
        !          1723: }
        !          1724: 
        !          1725: static const char * PTRFASTCALL
        !          1726: PREFIX(skipS)(const ENCODING *enc, const char *ptr)
        !          1727: {
        !          1728:   for (;;) {
        !          1729:     switch (BYTE_TYPE(enc, ptr)) {
        !          1730:     case BT_LF:
        !          1731:     case BT_CR:
        !          1732:     case BT_S:
        !          1733:       ptr += MINBPC(enc);
        !          1734:       break;
        !          1735:     default:
        !          1736:       return ptr;
        !          1737:     }
        !          1738:   }
        !          1739: }
        !          1740: 
        !          1741: static void PTRCALL
        !          1742: PREFIX(updatePosition)(const ENCODING *enc,
        !          1743:                        const char *ptr,
        !          1744:                        const char *end,
        !          1745:                        POSITION *pos)
        !          1746: {
        !          1747:   while (ptr != end) {
        !          1748:     switch (BYTE_TYPE(enc, ptr)) {
        !          1749: #define LEAD_CASE(n) \
        !          1750:     case BT_LEAD ## n: \
        !          1751:       ptr += n; \
        !          1752:       break;
        !          1753:     LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
        !          1754: #undef LEAD_CASE
        !          1755:     case BT_LF:
        !          1756:       pos->columnNumber = (XML_Size)-1;
        !          1757:       pos->lineNumber++;
        !          1758:       ptr += MINBPC(enc);
        !          1759:       break;
        !          1760:     case BT_CR:
        !          1761:       pos->lineNumber++;
        !          1762:       ptr += MINBPC(enc);
        !          1763:       if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
        !          1764:         ptr += MINBPC(enc);
        !          1765:       pos->columnNumber = (XML_Size)-1;
        !          1766:       break;
        !          1767:     default:
        !          1768:       ptr += MINBPC(enc);
        !          1769:       break;
        !          1770:     }
        !          1771:     pos->columnNumber++;
        !          1772:   }
        !          1773: }
        !          1774: 
        !          1775: #undef DO_LEAD_CASE
        !          1776: #undef MULTIBYTE_CASES
        !          1777: #undef INVALID_CASES
        !          1778: #undef CHECK_NAME_CASE
        !          1779: #undef CHECK_NAME_CASES
        !          1780: #undef CHECK_NMSTRT_CASE
        !          1781: #undef CHECK_NMSTRT_CASES
        !          1782: 
        !          1783: #endif /* XML_TOK_IMPL_C */

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