Home | History | Annotate | Download | only in expat
      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_PARTIAL;
    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 */
   1784