Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.