LCOV - code coverage report
Current view: top level - parser/expat/lib - xmltok_impl.c (source / functions) Hit Total Coverage
Test: output.info Lines: 255 904 28.2 %
Date: 2017-07-14 16:53:18 Functions: 14 87 16.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13