home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / exml.lha / exml / expat / xmltok / xmltok.c < prev    next >
C/C++ Source or Header  |  1999-04-13  |  29KB  |  1,142 lines

  1. /*
  2. The contents of this file are subject to the Mozilla Public License
  3. Version 1.0 (the "License"); you may not use this file except in
  4. compliance with the License. You may obtain a copy of the License at
  5. http://www.mozilla.org/MPL/
  6.  
  7. Software distributed under the License is distributed on an "AS IS"
  8. basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  9. License for the specific language governing rights and limitations
  10. under the License.
  11.  
  12. The Original Code is expat.
  13.  
  14. The Initial Developer of the Original Code is James Clark.
  15. Portions created by James Clark are Copyright (C) 1998
  16. James Clark. All Rights Reserved.
  17.  
  18. Contributor(s):
  19. */
  20.  
  21. #include "xmldef.h"
  22. #include "xmltok.h"
  23. #include "nametab.h"
  24.  
  25. #define VTABLE1 \
  26.   { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \
  27.   { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
  28.   PREFIX(sameName), \
  29.   PREFIX(nameMatchesAscii), \
  30.   PREFIX(nameLength), \
  31.   PREFIX(skipS), \
  32.   PREFIX(getAtts), \
  33.   PREFIX(charRefNumber), \
  34.   PREFIX(predefinedEntityName), \
  35.   PREFIX(updatePosition), \
  36.   PREFIX(isPublicId)
  37.  
  38. #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
  39.  
  40. #define UCS2_GET_NAMING(pages, hi, lo) \
  41.    (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
  42.  
  43. /* A 2 byte UTF-8 representation splits the characters 11 bits
  44. between the bottom 5 and 6 bits of the bytes.
  45. We need 8 bits to index into pages, 3 bits to add to that index and
  46. 5 bits to generate the mask. */
  47. #define UTF8_GET_NAMING2(pages, byte) \
  48.     (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
  49.                       + ((((byte)[0]) & 3) << 1) \
  50.                       + ((((byte)[1]) >> 5) & 1)] \
  51.          & (1 << (((byte)[1]) & 0x1F)))
  52.  
  53. /* A 3 byte UTF-8 representation splits the characters 16 bits
  54. between the bottom 4, 6 and 6 bits of the bytes.
  55. We need 8 bits to index into pages, 3 bits to add to that index and
  56. 5 bits to generate the mask. */
  57. #define UTF8_GET_NAMING3(pages, byte) \
  58.   (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
  59.                              + ((((byte)[1]) >> 2) & 0xF)] \
  60.                << 3) \
  61.                       + ((((byte)[1]) & 3) << 1) \
  62.                       + ((((byte)[2]) >> 5) & 1)] \
  63.          & (1 << (((byte)[2]) & 0x1F)))
  64.  
  65. #define UTF8_GET_NAMING(pages, p, n) \
  66.   ((n) == 2 \
  67.   ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
  68.   : ((n) == 3 \
  69.      ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
  70.      : 0))
  71.  
  72. #define UTF8_INVALID3(p) \
  73.   ((*p) == 0xED \
  74.   ? (((p)[1] & 0x20) != 0) \
  75.   : ((*p) == 0xEF \
  76.      ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
  77.      : 0))
  78.  
  79. #define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
  80.  
  81. static
  82. int isNever(const ENCODING *enc, const char *p)
  83. {
  84.   return 0;
  85. }
  86.  
  87. static
  88. int utf8_isName2(const ENCODING *enc, const char *p)
  89. {
  90.   return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
  91. }
  92.  
  93. static
  94. int utf8_isName3(const ENCODING *enc, const char *p)
  95. {
  96.   return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
  97. }
  98.  
  99. #define utf8_isName4 isNever
  100.  
  101. static
  102. int utf8_isNmstrt2(const ENCODING *enc, const char *p)
  103. {
  104.   return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
  105. }
  106.  
  107. static
  108. int utf8_isNmstrt3(const ENCODING *enc, const char *p)
  109. {
  110.   return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
  111. }
  112.  
  113. #define utf8_isNmstrt4 isNever
  114.  
  115. #define utf8_isInvalid2 isNever
  116.  
  117. static
  118. int utf8_isInvalid3(const ENCODING *enc, const char *p)
  119. {
  120.   return UTF8_INVALID3((const unsigned char *)p);
  121. }
  122.  
  123. static
  124. int utf8_isInvalid4(const ENCODING *enc, const char *p)
  125. {
  126.   return UTF8_INVALID4((const unsigned char *)p);
  127. }
  128.  
  129. struct normal_encoding {
  130.   ENCODING enc;
  131.   unsigned char type[256];
  132.   int (*isName2)(const ENCODING *, const char *);
  133.   int (*isName3)(const ENCODING *, const char *);
  134.   int (*isName4)(const ENCODING *, const char *);
  135.   int (*isNmstrt2)(const ENCODING *, const char *);
  136.   int (*isNmstrt3)(const ENCODING *, const char *);
  137.   int (*isNmstrt4)(const ENCODING *, const char *);
  138.   int (*isInvalid2)(const ENCODING *, const char *);
  139.   int (*isInvalid3)(const ENCODING *, const char *);
  140.   int (*isInvalid4)(const ENCODING *, const char *);
  141. };
  142.  
  143. #define NORMAL_VTABLE(E) \
  144.  E ## isName2, \
  145.  E ## isName3, \
  146.  E ## isName4, \
  147.  E ## isNmstrt2, \
  148.  E ## isNmstrt3, \
  149.  E ## isNmstrt4, \
  150.  E ## isInvalid2, \
  151.  E ## isInvalid3, \
  152.  E ## isInvalid4
  153.  
  154. static int checkCharRefNumber(int);
  155.  
  156. #include "xmltok_impl.h"
  157.  
  158. /* minimum bytes per character */
  159. #define MINBPC 1
  160. #define BYTE_TYPE(enc, p) \
  161.   (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
  162. #define BYTE_TO_ASCII(enc, p) (*p)
  163.  
  164. #define IS_NAME_CHAR(enc, p, n) \
  165.  (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
  166. #define IS_NMSTRT_CHAR(enc, p, n) \
  167.  (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
  168. #define IS_INVALID_CHAR(enc, p, n) \
  169.  (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
  170.  
  171. #define IS_NAME_CHAR_MINBPC(enc, p) (0)
  172. #define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
  173.  
  174. /* c is an ASCII character */
  175. #define CHAR_MATCHES(enc, p, c) (*(p) == c)
  176.  
  177. #define PREFIX(ident) normal_ ## ident
  178. #include "xmltok_impl.c"
  179.  
  180. #undef MINBPC
  181. #undef BYTE_TYPE
  182. #undef BYTE_TO_ASCII
  183. #undef CHAR_MATCHES
  184. #undef IS_NAME_CHAR
  185. #undef IS_NAME_CHAR_MINBPC
  186. #undef IS_NMSTRT_CHAR
  187. #undef IS_NMSTRT_CHAR_MINBPC
  188. #undef IS_INVALID_CHAR
  189.  
  190. enum {  /* UTF8_cvalN is value of masked first byte of N byte sequence */
  191.   UTF8_cval1 = 0x00,
  192.   UTF8_cval2 = 0xc0,
  193.   UTF8_cval3 = 0xe0,
  194.   UTF8_cval4 = 0xf0
  195. };
  196.  
  197. static
  198. void utf8_toUtf8(const ENCODING *enc,
  199.          const char **fromP, const char *fromLim,
  200.          char **toP, const char *toLim)
  201. {
  202.   char *to;
  203.   const char *from;
  204.   if (fromLim - *fromP > toLim - *toP) {
  205.     /* Avoid copying partial characters. */
  206.     for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
  207.       if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
  208.     break;
  209.   }
  210.   for (to = *toP, from = *fromP; from != fromLim; from++, to++)
  211.     *to = *from;
  212.   *fromP = from;
  213.   *toP = to;
  214. }
  215.  
  216. static
  217. void utf8_toUtf16(const ENCODING *enc,
  218.           const char **fromP, const char *fromLim,
  219.           unsigned short **toP, const unsigned short *toLim)
  220. {
  221.   unsigned short *to = *toP;
  222.   const char *from = *fromP;
  223.   while (from != fromLim && to != toLim) {
  224.     switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
  225.     case BT_LEAD2:
  226.       *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
  227.       from += 2;
  228.       break;
  229.     case BT_LEAD3:
  230.       *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
  231.       from += 3;
  232.       break;
  233.     case BT_LEAD4:
  234.       {
  235.     unsigned long n;
  236.     if (to + 1 == toLim)
  237.       break;
  238.     n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
  239.     n -= 0x10000;
  240.     to[0] = (unsigned short)((n >> 10) | 0xD800);
  241.     to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
  242.     to += 2;
  243.     from += 4;
  244.       }
  245.       break;
  246.     default:
  247.       *to++ = *from++;
  248.       break;
  249.     }
  250.   }
  251.   *fromP = from;
  252.   *toP = to;
  253. }
  254.  
  255. static const struct normal_encoding utf8_encoding = {
  256.   { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
  257.   {
  258. #include "asciitab.h"
  259. #include "utf8tab.h"
  260.   },
  261.   NORMAL_VTABLE(utf8_)
  262. };
  263.  
  264. static const struct normal_encoding internal_utf8_encoding = {
  265.   { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
  266.   {
  267. #include "iasciitab.h"
  268. #include "utf8tab.h"
  269.   },
  270.   NORMAL_VTABLE(utf8_)
  271. };
  272.  
  273. static
  274. void latin1_toUtf8(const ENCODING *enc,
  275.            const char **fromP, const char *fromLim,
  276.            char **toP, const char *toLim)
  277. {
  278.   for (;;) {
  279.     unsigned char c;
  280.     if (*fromP == fromLim)
  281.       break;
  282.     c = (unsigned char)**fromP;
  283.     if (c & 0x80) {
  284.       if (toLim - *toP < 2)
  285.     break;
  286.       *(*toP)++ = ((c >> 6) | UTF8_cval2);
  287.       *(*toP)++ = ((c & 0x3f) | 0x80);
  288.       (*fromP)++;
  289.     }
  290.     else {
  291.       if (*toP == toLim)
  292.     break;
  293.       *(*toP)++ = *(*fromP)++;
  294.     }
  295.   }
  296. }
  297.  
  298. static
  299. void latin1_toUtf16(const ENCODING *enc,
  300.             const char **fromP, const char *fromLim,
  301.             unsigned short **toP, const unsigned short *toLim)
  302. {
  303.   while (*fromP != fromLim && *toP != toLim)
  304.     *(*toP)++ = (unsigned char)*(*fromP)++;
  305. }
  306.  
  307. static const struct normal_encoding latin1_encoding = {
  308.   { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
  309.   {
  310. #include "asciitab.h"
  311. #include "latin1tab.h"
  312.   }
  313. };
  314.  
  315. static
  316. void ascii_toUtf8(const ENCODING *enc,
  317.           const char **fromP, const char *fromLim,
  318.           char **toP, const char *toLim)
  319. {
  320.   while (*fromP != fromLim && *toP != toLim)
  321.     *(*toP)++ = *(*fromP)++;
  322. }
  323.  
  324. static const struct normal_encoding ascii_encoding = {
  325.   { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
  326.   {
  327. #include "asciitab.h"
  328. /* BT_NONXML == 0 */
  329.   }
  330. };
  331.  
  332. #undef PREFIX
  333.  
  334. static int unicode_byte_type(char hi, char lo)
  335. {
  336.   switch ((unsigned char)hi) {
  337.   case 0xD8: case 0xD9: case 0xDA: case 0xDB:
  338.     return BT_LEAD4;
  339.   case 0xDC: case 0xDD: case 0xDE: case 0xDF:
  340.     return BT_TRAIL;
  341.   case 0xFF:
  342.     switch ((unsigned char)lo) {
  343.     case 0xFF:
  344.     case 0xFE:
  345.       return BT_NONXML;
  346.     }
  347.     break;
  348.   }
  349.   return BT_NONASCII;
  350. }
  351.  
  352. #define DEFINE_UTF16_TO_UTF8 \
  353. static \
  354. void PREFIX(toUtf8)(const ENCODING *enc, \
  355.             const char **fromP, const char *fromLim, \
  356.             char **toP, const char *toLim) \
  357. { \
  358.   const char *from; \
  359.   for (from = *fromP; from != fromLim; from += 2) { \
  360.     int plane; \
  361.     unsigned char lo2; \
  362.     unsigned char lo = GET_LO(from); \
  363.     unsigned char hi = GET_HI(from); \
  364.     switch (hi) { \
  365.     case 0: \
  366.       if (lo < 0x80) { \
  367.         if (*toP == toLim) { \
  368.           *fromP = from; \
  369.       return; \
  370.         } \
  371.         *(*toP)++ = lo; \
  372.         break; \
  373.       } \
  374.       /* fall through */ \
  375.     case 0x1: case 0x2: case 0x3: \
  376.     case 0x4: case 0x5: case 0x6: case 0x7: \
  377.       if (toLim -  *toP < 2) { \
  378.         *fromP = from; \
  379.     return; \
  380.       } \
  381.       *(*toP)++ = ((lo >> 6) | (hi << 2) |  UTF8_cval2); \
  382.       *(*toP)++ = ((lo & 0x3f) | 0x80); \
  383.       break; \
  384.     default: \
  385.       if (toLim -  *toP < 3)  { \
  386.         *fromP = from; \
  387.     return; \
  388.       } \
  389.       /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
  390.       *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
  391.       *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
  392.       *(*toP)++ = ((lo & 0x3f) | 0x80); \
  393.       break; \
  394.     case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
  395.       if (toLim -  *toP < 4) { \
  396.     *fromP = from; \
  397.     return; \
  398.       } \
  399.       plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
  400.       *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
  401.       *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
  402.       from += 2; \
  403.       lo2 = GET_LO(from); \
  404.       *(*toP)++ = (((lo & 0x3) << 4) \
  405.                | ((GET_HI(from) & 0x3) << 2) \
  406.            | (lo2 >> 6) \
  407.            | 0x80); \
  408.       *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
  409.       break; \
  410.     } \
  411.   } \
  412.   *fromP = from; \
  413. }
  414.  
  415. #define DEFINE_UTF16_TO_UTF16 \
  416. static \
  417. void PREFIX(toUtf16)(const ENCODING *enc, \
  418.              const char **fromP, const char *fromLim, \
  419.              unsigned short **toP, const unsigned short *toLim) \
  420. { \
  421.   /* Avoid copying first half only of surrogate */ \
  422.   if (fromLim - *fromP > ((toLim - *toP) << 1) \
  423.       && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
  424.     fromLim -= 2; \
  425.   for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
  426.     *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
  427. }
  428.  
  429. #define PREFIX(ident) little2_ ## ident
  430. #define MINBPC 2
  431. #define BYTE_TYPE(enc, p) \
  432.  ((p)[1] == 0 \
  433.   ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
  434.   : unicode_byte_type((p)[1], (p)[0]))
  435. #define BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
  436. #define CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
  437. #define IS_NAME_CHAR(enc, p, n) (0)
  438. #define IS_NAME_CHAR_MINBPC(enc, p) \
  439.   UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
  440. #define IS_NMSTRT_CHAR(enc, p, n) (0)
  441. #define IS_NMSTRT_CHAR_MINBPC(enc, p) \
  442.   UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
  443.  
  444. #include "xmltok_impl.c"
  445.  
  446. #define SET2(ptr, ch) \
  447.   (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
  448. #define GET_LO(ptr) ((unsigned char)(ptr)[0])
  449. #define GET_HI(ptr) ((unsigned char)(ptr)[1])
  450.  
  451. DEFINE_UTF16_TO_UTF8
  452. DEFINE_UTF16_TO_UTF16
  453.  
  454. #undef SET2
  455. #undef GET_LO
  456. #undef GET_HI
  457. #undef MINBPC
  458. #undef BYTE_TYPE
  459. #undef BYTE_TO_ASCII
  460. #undef CHAR_MATCHES
  461. #undef IS_NAME_CHAR
  462. #undef IS_NAME_CHAR_MINBPC
  463. #undef IS_NMSTRT_CHAR
  464. #undef IS_NMSTRT_CHAR_MINBPC
  465. #undef IS_INVALID_CHAR
  466.  
  467. static const struct normal_encoding little2_encoding = { 
  468.   { VTABLE, 2, 0,
  469. #if BYTE_ORDER == 12
  470.     1
  471. #else
  472.     0
  473. #endif
  474.   },
  475. #include "asciitab.h"
  476. #include "latin1tab.h"
  477. };
  478.  
  479. #if BYTE_ORDER != 21
  480.  
  481. static const struct normal_encoding internal_little2_encoding = { 
  482.   { VTABLE, 2, 0, 1 },
  483. #include "iasciitab.h"
  484. #include "latin1tab.h"
  485. };
  486.  
  487. #endif
  488.  
  489. #undef PREFIX
  490.  
  491. #define PREFIX(ident) big2_ ## ident
  492. #define MINBPC 2
  493. /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
  494. #define BYTE_TYPE(enc, p) \
  495.  ((p)[0] == 0 \
  496.   ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
  497.   : unicode_byte_type((p)[0], (p)[1]))
  498. #define BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
  499. #define CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
  500. #define IS_NAME_CHAR(enc, p, n) 0
  501. #define IS_NAME_CHAR_MINBPC(enc, p) \
  502.   UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
  503. #define IS_NMSTRT_CHAR(enc, p, n) (0)
  504. #define IS_NMSTRT_CHAR_MINBPC(enc, p) \
  505.   UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
  506.  
  507. #include "xmltok_impl.c"
  508.  
  509. #define SET2(ptr, ch) \
  510.   (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
  511. #define GET_LO(ptr) ((unsigned char)(ptr)[1])
  512. #define GET_HI(ptr) ((unsigned char)(ptr)[0])
  513.  
  514. DEFINE_UTF16_TO_UTF8
  515. DEFINE_UTF16_TO_UTF16
  516.  
  517. #undef SET2
  518. #undef GET_LO
  519. #undef GET_HI
  520. #undef MINBPC
  521. #undef BYTE_TYPE
  522. #undef BYTE_TO_ASCII
  523. #undef CHAR_MATCHES
  524. #undef IS_NAME_CHAR
  525. #undef IS_NAME_CHAR_MINBPC
  526. #undef IS_NMSTRT_CHAR
  527. #undef IS_NMSTRT_CHAR_MINBPC
  528. #undef IS_INVALID_CHAR
  529.  
  530. static const struct normal_encoding big2_encoding = {
  531.   { VTABLE, 2, 0,
  532. #if BYTE_ORDER == 21
  533.   1
  534. #else
  535.   0
  536. #endif
  537.   },
  538. #include "asciitab.h"
  539. #include "latin1tab.h"
  540. };
  541.  
  542. #if BYTE_ORDER != 12
  543.  
  544. static const struct normal_encoding internal_big2_encoding = {
  545.   { VTABLE, 2, 0, 1 },
  546. #include "iasciitab.h"
  547. #include "latin1tab.h"
  548. };
  549.  
  550. #endif
  551.  
  552. #undef PREFIX
  553.  
  554. static
  555. int streqci(const char *s1, const char *s2)
  556. {
  557.   for (;;) {
  558.     char c1 = *s1++;
  559.     char c2 = *s2++;
  560.     if ('a' <= c1 && c1 <= 'z')
  561.       c1 += 'A' - 'a';
  562.     if ('a' <= c2 && c2 <= 'z')
  563.       c2 += 'A' - 'a';
  564.     if (c1 != c2)
  565.       return 0;
  566.     if (!c1)
  567.       break;
  568.   }
  569.   return 1;
  570. }
  571.  
  572. static
  573. int initScan(const ENCODING *enc, int state, const char *ptr, const char *end,
  574.          const char **nextTokPtr)
  575. {
  576.   const ENCODING **encPtr;
  577.  
  578.   if (ptr == end)
  579.     return XML_TOK_NONE;
  580.   encPtr = ((const INIT_ENCODING *)enc)->encPtr;
  581.   if (ptr + 1 == end) {
  582.     switch ((unsigned char)*ptr) {
  583.     case 0xFE:
  584.     case 0xFF:
  585.     case 0x00:
  586.     case 0x3C:
  587.       return XML_TOK_PARTIAL;
  588.     }
  589.   }
  590.   else {
  591.     switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
  592.     case 0x003C:
  593.       *encPtr = &big2_encoding.enc;
  594.       return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
  595.     case 0xFEFF:
  596.       *nextTokPtr = ptr + 2;
  597.       *encPtr = &big2_encoding.enc;
  598.       return XML_TOK_BOM;
  599.     case 0x3C00:
  600.       *encPtr = &little2_encoding.enc;
  601.       return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
  602.     case 0xFFFE:
  603.       *nextTokPtr = ptr + 2;
  604.       *encPtr = &little2_encoding.enc;
  605.       return XML_TOK_BOM;
  606.     }
  607.   }
  608.   *encPtr = &utf8_encoding.enc;
  609.   return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
  610. }
  611.  
  612. static
  613. int initScanProlog(const ENCODING *enc, const char *ptr, const char *end,
  614.            const char **nextTokPtr)
  615. {
  616.   return initScan(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
  617. }
  618.  
  619. static
  620. int initScanContent(const ENCODING *enc, const char *ptr, const char *end,
  621.             const char **nextTokPtr)
  622. {
  623.   return initScan(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
  624. }
  625.  
  626. static
  627. void initUpdatePosition(const ENCODING *enc, const char *ptr,
  628.             const char *end, POSITION *pos)
  629. {
  630.   normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
  631. }
  632.  
  633. const ENCODING *XmlGetUtf8InternalEncoding()
  634. {
  635.   return &internal_utf8_encoding.enc;
  636. }
  637.  
  638. const ENCODING *XmlGetUtf16InternalEncoding()
  639. {
  640. #if BYTE_ORDER == 12
  641.   return &internal_little2_encoding.enc;
  642. #elif BYTE_ORDER == 21
  643.   return &internal_big2_encoding.enc;
  644. #else
  645.   const short n = 1;
  646.   return *(const char *)&n ? &internal_little2_encoding.enc : &internal_big2_encoding.enc;
  647. #endif
  648. }
  649.  
  650. int XmlInitEncoding(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
  651. {
  652.   if (name) {
  653.     if (streqci(name, "ISO-8859-1")) {
  654.       *encPtr = &latin1_encoding.enc;
  655.       return 1;
  656.     }
  657.     if (streqci(name, "UTF-8")) {
  658.       *encPtr = &utf8_encoding.enc;
  659.       return 1;
  660.     }
  661.     if (streqci(name, "US-ASCII")) {
  662.       *encPtr = &ascii_encoding.enc;
  663.       return 1;
  664.     }
  665.     if (!streqci(name, "UTF-16"))
  666.       return 0;
  667.   }
  668.   p->initEnc.scanners[XML_PROLOG_STATE] = initScanProlog;
  669.   p->initEnc.scanners[XML_CONTENT_STATE] = initScanContent;
  670.   p->initEnc.updatePosition = initUpdatePosition;
  671.   p->initEnc.minBytesPerChar = 1;
  672.   p->encPtr = encPtr;
  673.   *encPtr = &(p->initEnc);
  674.   return 1;
  675. }
  676.  
  677. static
  678. int toAscii(const ENCODING *enc, const char *ptr, const char *end)
  679. {
  680.   char buf[1];
  681.   char *p = buf;
  682.   XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
  683.   if (p == buf)
  684.     return -1;
  685.   else
  686.     return buf[0];
  687. }
  688.  
  689. static
  690. int isSpace(int c)
  691. {
  692.   switch (c) {
  693.   case ' ':
  694.   case '\r':
  695.   case '\n':
  696.   case '\t':
  697.     return 1;
  698.   }
  699.   return 0;
  700. }
  701.  
  702. /* Return 1 if there's just optional white space
  703. or there's an S followed by name=val. */
  704. static
  705. int parsePseudoAttribute(const ENCODING *enc,
  706.              const char *ptr,
  707.              const char *end,
  708.              const char **namePtr,
  709.              const char **valPtr,
  710.              const char **nextTokPtr)
  711. {
  712.   int c;
  713.   char open;
  714.   if (ptr == end) {
  715.     *namePtr = 0;
  716.     return 1;
  717.   }
  718.   if (!isSpace(toAscii(enc, ptr, end))) {
  719.     *nextTokPtr = ptr;
  720.     return 0;
  721.   }
  722.   do {
  723.     ptr += enc->minBytesPerChar;
  724.   } while (isSpace(toAscii(enc, ptr, end)));
  725.   if (ptr == end) {
  726.     *namePtr = 0;
  727.     return 1;
  728.   }
  729.   *namePtr = ptr;
  730.   for (;;) {
  731.     c = toAscii(enc, ptr, end);
  732.     if (c == -1) {
  733.       *nextTokPtr = ptr;
  734.       return 0;
  735.     }
  736.     if (c == '=')
  737.       break;
  738.     if (isSpace(c)) {
  739.       do {
  740.     ptr += enc->minBytesPerChar;
  741.       } while (isSpace(c = toAscii(enc, ptr, end)));
  742.       if (c != '=') {
  743.     *nextTokPtr = ptr;
  744.     return 0;
  745.       }
  746.       break;
  747.     }
  748.     ptr += enc->minBytesPerChar;
  749.   }
  750.   if (ptr == *namePtr) {
  751.     *nextTokPtr = ptr;
  752.     return 0;
  753.   }
  754.   ptr += enc->minBytesPerChar;
  755.   c = toAscii(enc, ptr, end);
  756.   while (isSpace(c)) {
  757.     ptr += enc->minBytesPerChar;
  758.     c = toAscii(enc, ptr, end);
  759.   }
  760.   if (c != '"' && c != '\'') {
  761.     *nextTokPtr = ptr;
  762.     return 0;
  763.   }
  764.   open = c;
  765.   ptr += enc->minBytesPerChar;
  766.   *valPtr = ptr;
  767.   for (;; ptr += enc->minBytesPerChar) {
  768.     c = toAscii(enc, ptr, end);
  769.     if (c == open)
  770.       break;
  771.     if (!('a' <= c && c <= 'z')
  772.     && !('A' <= c && c <= 'Z')
  773.     && !('0' <= c && c <= '9')
  774.     && c != '.'
  775.     && c != '-'
  776.     && c != '_') {
  777.       *nextTokPtr = ptr;
  778.       return 0;
  779.     }
  780.   }
  781.   *nextTokPtr = ptr + enc->minBytesPerChar;
  782.   return 1;
  783. }
  784.  
  785. static
  786. const ENCODING *findEncoding(const ENCODING *enc, const char *ptr, const char *end)
  787. {
  788. #define ENCODING_MAX 128
  789.   char buf[ENCODING_MAX];
  790.   char *p = buf;
  791.   int i;
  792.   XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
  793.   if (ptr != end)
  794.     return 0;
  795.   *p = 0;
  796.   for (i = 0; buf[i]; i++) {
  797.     if ('a' <= buf[i] && buf[i] <= 'z')
  798.       buf[i] +=  'A' - 'a';
  799.   }
  800.   if (streqci(buf, "UTF-8"))
  801.     return &utf8_encoding.enc;
  802.   if (streqci(buf, "ISO-8859-1"))
  803.     return &latin1_encoding.enc;
  804.   if (streqci(buf, "US-ASCII"))
  805.     return &ascii_encoding.enc;
  806.   if (streqci(buf, "UTF-16")) {
  807.     static const unsigned short n = 1;
  808.     if (enc->minBytesPerChar == 2)
  809.       return enc;
  810.     return &big2_encoding.enc;
  811.   }
  812.   return 0;  
  813. }
  814.  
  815. int XmlParseXmlDecl(int isGeneralTextEntity,
  816.             const ENCODING *enc,
  817.             const char *ptr,
  818.             const char *end,
  819.             const char **badPtr,
  820.             const char **versionPtr,
  821.             const char **encodingName,
  822.             const ENCODING **encoding,
  823.             int *standalone)
  824. {
  825.   const char *val = 0;
  826.   const char *name = 0;
  827.   ptr += 5 * enc->minBytesPerChar;
  828.   end -= 2 * enc->minBytesPerChar;
  829.   if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) {
  830.     *badPtr = ptr;
  831.     return 0;
  832.   }
  833.   if (!XmlNameMatchesAscii(enc, name, "version")) {
  834.     if (!isGeneralTextEntity) {
  835.       *badPtr = name;
  836.       return 0;
  837.     }
  838.   }
  839.   else {
  840.     if (versionPtr)
  841.       *versionPtr = val;
  842.     if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
  843.       *badPtr = ptr;
  844.       return 0;
  845.     }
  846.     if (!name) {
  847.       if (isGeneralTextEntity) {
  848.     /* a TextDecl must have an EncodingDecl */
  849.     *badPtr = ptr;
  850.     return 0;
  851.       }
  852.       return 1;
  853.     }
  854.   }
  855.   if (XmlNameMatchesAscii(enc, name, "encoding")) {
  856.     int c = toAscii(enc, val, end);
  857.     if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) {
  858.       *badPtr = val;
  859.       return 0;
  860.     }
  861.     if (encodingName)
  862.       *encodingName = val;
  863.     if (encoding)
  864.       *encoding = findEncoding(enc, val, ptr - enc->minBytesPerChar);
  865.     if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
  866.       *badPtr = ptr;
  867.       return 0;
  868.     }
  869.     if (!name)
  870.       return 1;
  871.   }
  872.   if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) {
  873.     *badPtr = name;
  874.     return 0;
  875.   }
  876.   if (XmlNameMatchesAscii(enc, val, "yes")) {
  877.     if (standalone)
  878.       *standalone = 1;
  879.   }
  880.   else if (XmlNameMatchesAscii(enc, val, "no")) {
  881.     if (standalone)
  882.       *standalone = 0;
  883.   }
  884.   else {
  885.     *badPtr = val;
  886.     return 0;
  887.   }
  888.   while (isSpace(toAscii(enc, ptr, end)))
  889.     ptr += enc->minBytesPerChar;
  890.   if (ptr != end) {
  891.     *badPtr = ptr;
  892.     return 0;
  893.   }
  894.   return 1;
  895. }
  896.  
  897. static
  898. int checkCharRefNumber(int result)
  899. {
  900.   switch (result >> 8) {
  901.   case 0xD8: case 0xD9: case 0xDA: case 0xDB:
  902.   case 0xDC: case 0xDD: case 0xDE: case 0xDF:
  903.     return -1;
  904.   case 0:
  905.     if (latin1_encoding.type[result] == BT_NONXML)
  906.       return -1;
  907.     break;
  908.   case 0xFF:
  909.     if (result == 0xFFFE || result == 0xFFFF)
  910.       return -1;
  911.     break;
  912.   }
  913.   return result;
  914. }
  915.  
  916. int XmlUtf8Encode(int c, char *buf)
  917. {
  918.   enum {
  919.     /* minN is minimum legal resulting value for N byte sequence */
  920.     min2 = 0x80,
  921.     min3 = 0x800,
  922.     min4 = 0x10000
  923.   };
  924.  
  925.   if (c < 0)
  926.     return 0;
  927.   if (c < min2) {
  928.     buf[0] = (c | UTF8_cval1);
  929.     return 1;
  930.   }
  931.   if (c < min3) {
  932.     buf[0] = ((c >> 6) | UTF8_cval2);
  933.     buf[1] = ((c & 0x3f) | 0x80);
  934.     return 2;
  935.   }
  936.   if (c < min4) {
  937.     buf[0] = ((c >> 12) | UTF8_cval3);
  938.     buf[1] = (((c >> 6) & 0x3f) | 0x80);
  939.     buf[2] = ((c & 0x3f) | 0x80);
  940.     return 3;
  941.   }
  942.   if (c < 0x110000) {
  943.     buf[0] = ((c >> 18) | UTF8_cval4);
  944.     buf[1] = (((c >> 12) & 0x3f) | 0x80);
  945.     buf[2] = (((c >> 6) & 0x3f) | 0x80);
  946.     buf[3] = ((c & 0x3f) | 0x80);
  947.     return 4;
  948.   }
  949.   return 0;
  950. }
  951.  
  952. int XmlUtf16Encode(int charNum, unsigned short *buf)
  953. {
  954.   if (charNum < 0)
  955.     return 0;
  956.   if (charNum < 0x10000) {
  957.     buf[0] = charNum;
  958.     return 1;
  959.   }
  960.   if (charNum < 0x110000) {
  961.     charNum -= 0x10000;
  962.     buf[0] = (charNum >> 10) + 0xD800;
  963.     buf[1] = (charNum & 0x3FF) + 0xDC00;
  964.     return 2;
  965.   }
  966.   return 0;
  967. }
  968.  
  969. struct unknown_encoding {
  970.   struct normal_encoding normal;
  971.   int (*convert)(void *userData, const char *p);
  972.   void *userData;
  973.   unsigned short utf16[256];
  974.   char utf8[256][4];
  975. };
  976.  
  977. int XmlSizeOfUnknownEncoding()
  978. {
  979.   return sizeof(struct unknown_encoding);
  980. }
  981.  
  982. static
  983. int unknown_isName(const ENCODING *enc, const char *p)
  984. {
  985.   int c = ((const struct unknown_encoding *)enc)
  986.       ->convert(((const struct unknown_encoding *)enc)->userData, p);
  987.   if (c & ~0xFFFF)
  988.     return 0;
  989.   return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
  990. }
  991.  
  992. static
  993. int unknown_isNmstrt(const ENCODING *enc, const char *p)
  994. {
  995.   int c = ((const struct unknown_encoding *)enc)
  996.       ->convert(((const struct unknown_encoding *)enc)->userData, p);
  997.   if (c & ~0xFFFF)
  998.     return 0;
  999.   return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
  1000. }
  1001.  
  1002. static
  1003. int unknown_isInvalid(const ENCODING *enc, const char *p)
  1004. {
  1005.   int c = ((const struct unknown_encoding *)enc)
  1006.        ->convert(((const struct unknown_encoding *)enc)->userData, p);
  1007.   return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
  1008. }
  1009.  
  1010. static
  1011. void unknown_toUtf8(const ENCODING *enc,
  1012.             const char **fromP, const char *fromLim,
  1013.             char **toP, const char *toLim)
  1014. {
  1015.   char buf[XML_UTF8_ENCODE_MAX];
  1016.   for (;;) {
  1017.     const char *utf8;
  1018.     int n;
  1019.     if (*fromP == fromLim)
  1020.       break;
  1021.     utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
  1022.     n = *utf8++;
  1023.     if (n == 0) {
  1024.       int c = ((const struct unknown_encoding *)enc)
  1025.           ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
  1026.       n = XmlUtf8Encode(c, buf);
  1027.       if (n > toLim - *toP)
  1028.     break;
  1029.       utf8 = buf;
  1030.       *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
  1031.              - (BT_LEAD2 - 2);
  1032.     }
  1033.     else {
  1034.       if (n > toLim - *toP)
  1035.     break;
  1036.       (*fromP)++;
  1037.     }
  1038.     do {
  1039.       *(*toP)++ = *utf8++;
  1040.     } while (--n != 0);
  1041.   }
  1042. }
  1043.  
  1044. static
  1045. void unknown_toUtf16(const ENCODING *enc,
  1046.              const char **fromP, const char *fromLim,
  1047.              unsigned short **toP, const unsigned short *toLim)
  1048. {
  1049.   while (*fromP != fromLim && *toP != toLim) {
  1050.     unsigned short c
  1051.       = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
  1052.     if (c == 0) {
  1053.       c = (unsigned short)((const struct unknown_encoding *)enc)
  1054.        ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
  1055.       *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
  1056.              - (BT_LEAD2 - 2);
  1057.     }
  1058.     else
  1059.       (*fromP)++;
  1060.     *(*toP)++ = c;
  1061.   }
  1062. }
  1063.  
  1064. ENCODING *
  1065. XmlInitUnknownEncoding(void *mem,
  1066.                int *table,
  1067.                int (*convert)(void *userData, const char *p),
  1068.                void *userData)
  1069. {
  1070.   int i;
  1071.   struct unknown_encoding *e = mem;
  1072.   for (i = 0; i < sizeof(struct normal_encoding); i++)
  1073.     ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
  1074.   for (i = 0; i < 128; i++)
  1075.     if (latin1_encoding.type[i] != BT_OTHER
  1076.         && latin1_encoding.type[i] != BT_NONXML
  1077.     && table[i] != i)
  1078.       return 0;
  1079.   for (i = 0; i < 256; i++) {
  1080.     int c = table[i];
  1081.     if (c == -1) {
  1082.       e->normal.type[i] = BT_MALFORM;
  1083.       /* This shouldn't really get used. */
  1084.       e->utf16[i] = 0xFFFF;
  1085.       e->utf8[i][0] = 1;
  1086.       e->utf8[i][1] = 0;
  1087.     }
  1088.     else if (c < 0) {
  1089.       if (c < -4)
  1090.     return 0;
  1091.       e->normal.type[i] = BT_LEAD2 - (c + 2);
  1092.       e->utf8[i][0] = 0;
  1093.       e->utf16[i] = 0;
  1094.     }
  1095.     else if (c < 0x80) {
  1096.       if (latin1_encoding.type[c] != BT_OTHER
  1097.       && latin1_encoding.type[c] != BT_NONXML
  1098.       && c != i)
  1099.     return 0;
  1100.       e->normal.type[i] = latin1_encoding.type[c];
  1101.       e->utf8[i][0] = 1;
  1102.       e->utf8[i][1] = (char)c;
  1103.       e->utf16[i] = c == 0 ? 0xFFFF : c;
  1104.     }
  1105.     else if (checkCharRefNumber(c) < 0) {
  1106.       e->normal.type[i] = BT_NONXML;
  1107.       /* This shouldn't really get used. */
  1108.       e->utf16[i] = 0xFFFF;
  1109.       e->utf8[i][0] = 1;
  1110.       e->utf8[i][1] = 0;
  1111.     }
  1112.     else {
  1113.       if (c > 0xFFFF)
  1114.     return 0;
  1115.       if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
  1116.     e->normal.type[i] = BT_NMSTRT;
  1117.       else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
  1118.     e->normal.type[i] = BT_NAME;
  1119.       else
  1120.     e->normal.type[i] = BT_OTHER;
  1121.       e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
  1122.       e->utf16[i] = c;
  1123.     }
  1124.   }
  1125.   e->userData = userData;
  1126.   e->convert = convert;
  1127.   if (convert) {
  1128.     e->normal.isName2 = unknown_isName;
  1129.     e->normal.isName3 = unknown_isName;
  1130.     e->normal.isName4 = unknown_isName;
  1131.     e->normal.isNmstrt2 = unknown_isNmstrt;
  1132.     e->normal.isNmstrt3 = unknown_isNmstrt;
  1133.     e->normal.isNmstrt4 = unknown_isNmstrt;
  1134.     e->normal.isInvalid2 = unknown_isInvalid;
  1135.     e->normal.isInvalid3 = unknown_isInvalid;
  1136.     e->normal.isInvalid4 = unknown_isInvalid;
  1137.   }
  1138.   e->normal.enc.utf8Convert = unknown_toUtf8;
  1139.   e->normal.enc.utf16Convert = unknown_toUtf16;
  1140.   return &(e->normal.enc);
  1141. }
  1142.