Main Page | Class List | Directories | File List | Class Members | File Members

xmltok.c

Go to the documentation of this file.
00001 /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
00002    See the file COPYING for copying permission.
00003 */
00004 
00005 #include <stddef.h>
00006 
00007 #ifdef COMPILED_FROM_DSP
00008 #include "winconfig.h"
00009 #elif defined(MACOS_CLASSIC)
00010 #include "macconfig.h"
00011 #else
00012 #ifdef HAVE_EXPAT_CONFIG_H
00013 #include <expat_config.h>
00014 #endif
00015 #endif /* ndef COMPILED_FROM_DSP */
00016 
00017 #include "expat_external.h"
00018 #include "internal.h"
00019 #include "xmltok.h"
00020 #include "nametab.h"
00021 
00022 #ifdef XML_DTD
00023 #define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
00024 #else
00025 #define IGNORE_SECTION_TOK_VTABLE /* as nothing */
00026 #endif
00027 
00028 #define VTABLE1 \
00029   { PREFIX(prologTok), PREFIX(contentTok), \
00030     PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
00031   { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
00032   PREFIX(sameName), \
00033   PREFIX(nameMatchesAscii), \
00034   PREFIX(nameLength), \
00035   PREFIX(skipS), \
00036   PREFIX(getAtts), \
00037   PREFIX(charRefNumber), \
00038   PREFIX(predefinedEntityName), \
00039   PREFIX(updatePosition), \
00040   PREFIX(isPublicId)
00041 
00042 #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
00043 
00044 #define UCS2_GET_NAMING(pages, hi, lo) \
00045    (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
00046 
00047 /* A 2 byte UTF-8 representation splits the characters 11 bits between
00048    the bottom 5 and 6 bits of the bytes.  We need 8 bits to index into
00049    pages, 3 bits to add to that index and 5 bits to generate the mask.
00050 */
00051 #define UTF8_GET_NAMING2(pages, byte) \
00052     (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
00053                       + ((((byte)[0]) & 3) << 1) \
00054                       + ((((byte)[1]) >> 5) & 1)] \
00055          & (1 << (((byte)[1]) & 0x1F)))
00056 
00057 /* A 3 byte UTF-8 representation splits the characters 16 bits between
00058    the bottom 4, 6 and 6 bits of the bytes.  We need 8 bits to index
00059    into pages, 3 bits to add to that index and 5 bits to generate the
00060    mask.
00061 */
00062 #define UTF8_GET_NAMING3(pages, byte) \
00063   (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
00064                              + ((((byte)[1]) >> 2) & 0xF)] \
00065                        << 3) \
00066                       + ((((byte)[1]) & 3) << 1) \
00067                       + ((((byte)[2]) >> 5) & 1)] \
00068          & (1 << (((byte)[2]) & 0x1F)))
00069 
00070 #define UTF8_GET_NAMING(pages, p, n) \
00071   ((n) == 2 \
00072   ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
00073   : ((n) == 3 \
00074      ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
00075      : 0))
00076 
00077 /* Detection of invalid UTF-8 sequences is based on Table 3.1B
00078    of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
00079    with the additional restriction of not allowing the Unicode
00080    code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE).
00081    Implementation details:
00082      (A & 0x80) == 0     means A < 0x80
00083    and
00084      (A & 0xC0) == 0xC0  means A > 0xBF
00085 */
00086 
00087 #define UTF8_INVALID2(p) \
00088   ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
00089 
00090 #define UTF8_INVALID3(p) \
00091   (((p)[2] & 0x80) == 0 \
00092   || \
00093   ((*p) == 0xEF && (p)[1] == 0xBF \
00094     ? \
00095     (p)[2] > 0xBD \
00096     : \
00097     ((p)[2] & 0xC0) == 0xC0) \
00098   || \
00099   ((*p) == 0xE0 \
00100     ? \
00101     (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \
00102     : \
00103     ((p)[1] & 0x80) == 0 \
00104     || \
00105     ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
00106 
00107 #define UTF8_INVALID4(p) \
00108   (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 \
00109   || \
00110   ((p)[2] & 0x80) == 0 || ((p)[2] & 0xC0) == 0xC0 \
00111   || \
00112   ((*p) == 0xF0 \
00113     ? \
00114     (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \
00115     : \
00116     ((p)[1] & 0x80) == 0 \
00117     || \
00118     ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
00119 
00120 static int PTRFASTCALL
00121 isNever(const ENCODING *enc, const char *p)
00122 {
00123   return 0;
00124 }
00125 
00126 static int PTRFASTCALL
00127 utf8_isName2(const ENCODING *enc, const char *p)
00128 {
00129   return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
00130 }
00131 
00132 static int PTRFASTCALL
00133 utf8_isName3(const ENCODING *enc, const char *p)
00134 {
00135   return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
00136 }
00137 
00138 #define utf8_isName4 isNever
00139 
00140 static int PTRFASTCALL
00141 utf8_isNmstrt2(const ENCODING *enc, const char *p)
00142 {
00143   return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
00144 }
00145 
00146 static int PTRFASTCALL
00147 utf8_isNmstrt3(const ENCODING *enc, const char *p)
00148 {
00149   return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
00150 }
00151 
00152 #define utf8_isNmstrt4 isNever
00153 
00154 static int PTRFASTCALL
00155 utf8_isInvalid2(const ENCODING *enc, const char *p)
00156 {
00157   return UTF8_INVALID2((const unsigned char *)p);
00158 }
00159 
00160 static int PTRFASTCALL
00161 utf8_isInvalid3(const ENCODING *enc, const char *p)
00162 {
00163   return UTF8_INVALID3((const unsigned char *)p);
00164 }
00165 
00166 static int PTRFASTCALL
00167 utf8_isInvalid4(const ENCODING *enc, const char *p)
00168 {
00169   return UTF8_INVALID4((const unsigned char *)p);
00170 }
00171 
00172 struct normal_encoding {
00173   ENCODING enc;
00174   unsigned char type[256];
00175 #ifdef XML_MIN_SIZE
00176   int (PTRFASTCALL *byteType)(const ENCODING *, const char *);
00177   int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
00178   int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
00179   int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
00180   int (PTRCALL *charMatches)(const ENCODING *, const char *, int);
00181 #endif /* XML_MIN_SIZE */
00182   int (PTRFASTCALL *isName2)(const ENCODING *, const char *);
00183   int (PTRFASTCALL *isName3)(const ENCODING *, const char *);
00184   int (PTRFASTCALL *isName4)(const ENCODING *, const char *);
00185   int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
00186   int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
00187   int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
00188   int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
00189   int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
00190   int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
00191 };
00192 
00193 #define AS_NORMAL_ENCODING(enc)   ((const struct normal_encoding *) (enc))
00194 
00195 #ifdef XML_MIN_SIZE
00196 
00197 #define STANDARD_VTABLE(E) \
00198  E ## byteType, \
00199  E ## isNameMin, \
00200  E ## isNmstrtMin, \
00201  E ## byteToAscii, \
00202  E ## charMatches,
00203 
00204 #else
00205 
00206 #define STANDARD_VTABLE(E) /* as nothing */
00207 
00208 #endif
00209 
00210 #define NORMAL_VTABLE(E) \
00211  E ## isName2, \
00212  E ## isName3, \
00213  E ## isName4, \
00214  E ## isNmstrt2, \
00215  E ## isNmstrt3, \
00216  E ## isNmstrt4, \
00217  E ## isInvalid2, \
00218  E ## isInvalid3, \
00219  E ## isInvalid4
00220 
00221 static int FASTCALL checkCharRefNumber(int);
00222 
00223 #include "xmltok_impl.h"
00224 #include "ascii.h"
00225 
00226 #ifdef XML_MIN_SIZE
00227 #define sb_isNameMin isNever
00228 #define sb_isNmstrtMin isNever
00229 #endif
00230 
00231 #ifdef XML_MIN_SIZE
00232 #define MINBPC(enc) ((enc)->minBytesPerChar)
00233 #else
00234 /* minimum bytes per character */
00235 #define MINBPC(enc) 1
00236 #endif
00237 
00238 #define SB_BYTE_TYPE(enc, p) \
00239   (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
00240 
00241 #ifdef XML_MIN_SIZE
00242 static int PTRFASTCALL
00243 sb_byteType(const ENCODING *enc, const char *p)
00244 {
00245   return SB_BYTE_TYPE(enc, p);
00246 }
00247 #define BYTE_TYPE(enc, p) \
00248  (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
00249 #else
00250 #define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
00251 #endif
00252 
00253 #ifdef XML_MIN_SIZE
00254 #define BYTE_TO_ASCII(enc, p) \
00255  (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
00256 static int PTRFASTCALL
00257 sb_byteToAscii(const ENCODING *enc, const char *p)
00258 {
00259   return *p;
00260 }
00261 #else
00262 #define BYTE_TO_ASCII(enc, p) (*(p))
00263 #endif
00264 
00265 #define IS_NAME_CHAR(enc, p, n) \
00266  (AS_NORMAL_ENCODING(enc)->isName ## n(enc, p))
00267 #define IS_NMSTRT_CHAR(enc, p, n) \
00268  (AS_NORMAL_ENCODING(enc)->isNmstrt ## n(enc, p))
00269 #define IS_INVALID_CHAR(enc, p, n) \
00270  (AS_NORMAL_ENCODING(enc)->isInvalid ## n(enc, p))
00271 
00272 #ifdef XML_MIN_SIZE
00273 #define IS_NAME_CHAR_MINBPC(enc, p) \
00274  (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
00275 #define IS_NMSTRT_CHAR_MINBPC(enc, p) \
00276  (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
00277 #else
00278 #define IS_NAME_CHAR_MINBPC(enc, p) (0)
00279 #define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
00280 #endif
00281 
00282 #ifdef XML_MIN_SIZE
00283 #define CHAR_MATCHES(enc, p, c) \
00284  (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
00285 static int PTRCALL
00286 sb_charMatches(const ENCODING *enc, const char *p, int c)
00287 {
00288   return *p == c;
00289 }
00290 #else
00291 /* c is an ASCII character */
00292 #define CHAR_MATCHES(enc, p, c) (*(p) == c)
00293 #endif
00294 
00295 #define PREFIX(ident) normal_ ## ident
00296 #include "xmltok_impl.c"
00297 
00298 #undef MINBPC
00299 #undef BYTE_TYPE
00300 #undef BYTE_TO_ASCII
00301 #undef CHAR_MATCHES
00302 #undef IS_NAME_CHAR
00303 #undef IS_NAME_CHAR_MINBPC
00304 #undef IS_NMSTRT_CHAR
00305 #undef IS_NMSTRT_CHAR_MINBPC
00306 #undef IS_INVALID_CHAR
00307 
00308 enum {  /* UTF8_cvalN is value of masked first byte of N byte sequence */
00309   UTF8_cval1 = 0x00,
00310   UTF8_cval2 = 0xc0,
00311   UTF8_cval3 = 0xe0,
00312   UTF8_cval4 = 0xf0
00313 };
00314 
00315 static void PTRCALL
00316 utf8_toUtf8(const ENCODING *enc,
00317             const char **fromP, const char *fromLim,
00318             char **toP, const char *toLim)
00319 {
00320   char *to;
00321   const char *from;
00322   if (fromLim - *fromP > toLim - *toP) {
00323     /* Avoid copying partial characters. */
00324     for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
00325       if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
00326         break;
00327   }
00328   for (to = *toP, from = *fromP; from != fromLim; from++, to++)
00329     *to = *from;
00330   *fromP = from;
00331   *toP = to;
00332 }
00333 
00334 static void PTRCALL
00335 utf8_toUtf16(const ENCODING *enc,
00336              const char **fromP, const char *fromLim,
00337              unsigned short **toP, const unsigned short *toLim)
00338 {
00339   unsigned short *to = *toP;
00340   const char *from = *fromP;
00341   while (from != fromLim && to != toLim) {
00342     switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
00343     case BT_LEAD2:
00344       *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
00345       from += 2;
00346       break;
00347     case BT_LEAD3:
00348       *to++ = (unsigned short)(((from[0] & 0xf) << 12)
00349                                | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
00350       from += 3;
00351       break;
00352     case BT_LEAD4:
00353       {
00354         unsigned long n;
00355         if (to + 1 == toLim)
00356           goto after;
00357         n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
00358             | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
00359         n -= 0x10000;
00360         to[0] = (unsigned short)((n >> 10) | 0xD800);
00361         to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
00362         to += 2;
00363         from += 4;
00364       }
00365       break;
00366     default:
00367       *to++ = *from++;
00368       break;
00369     }
00370   }
00371 after:
00372   *fromP = from;
00373   *toP = to;
00374 }
00375 
00376 #ifdef XML_NS
00377 static const struct normal_encoding utf8_encoding_ns = {
00378   { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
00379   {
00380 #include "asciitab.h"
00381 #include "utf8tab.h"
00382   },
00383   STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
00384 };
00385 #endif
00386 
00387 static const struct normal_encoding utf8_encoding = {
00388   { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
00389   {
00390 #define BT_COLON BT_NMSTRT
00391 #include "asciitab.h"
00392 #undef BT_COLON
00393 #include "utf8tab.h"
00394   },
00395   STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
00396 };
00397 
00398 #ifdef XML_NS
00399 
00400 static const struct normal_encoding internal_utf8_encoding_ns = {
00401   { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
00402   {
00403 #include "iasciitab.h"
00404 #include "utf8tab.h"
00405   },
00406   STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
00407 };
00408 
00409 #endif
00410 
00411 static const struct normal_encoding internal_utf8_encoding = {
00412   { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
00413   {
00414 #define BT_COLON BT_NMSTRT
00415 #include "iasciitab.h"
00416 #undef BT_COLON
00417 #include "utf8tab.h"
00418   },
00419   STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
00420 };
00421 
00422 static void PTRCALL
00423 latin1_toUtf8(const ENCODING *enc,
00424               const char **fromP, const char *fromLim,
00425               char **toP, const char *toLim)
00426 {
00427   for (;;) {
00428     unsigned char c;
00429     if (*fromP == fromLim)
00430       break;
00431     c = (unsigned char)**fromP;
00432     if (c & 0x80) {
00433       if (toLim - *toP < 2)
00434         break;
00435       *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
00436       *(*toP)++ = (char)((c & 0x3f) | 0x80);
00437       (*fromP)++;
00438     }
00439     else {
00440       if (*toP == toLim)
00441         break;
00442       *(*toP)++ = *(*fromP)++;
00443     }
00444   }
00445 }
00446 
00447 static void PTRCALL
00448 latin1_toUtf16(const ENCODING *enc,
00449                const char **fromP, const char *fromLim,
00450                unsigned short **toP, const unsigned short *toLim)
00451 {
00452   while (*fromP != fromLim && *toP != toLim)
00453     *(*toP)++ = (unsigned char)*(*fromP)++;
00454 }
00455 
00456 #ifdef XML_NS
00457 
00458 static const struct normal_encoding latin1_encoding_ns = {
00459   { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
00460   {
00461 #include "asciitab.h"
00462 #include "latin1tab.h"
00463   },
00464   STANDARD_VTABLE(sb_)
00465 };
00466 
00467 #endif
00468 
00469 static const struct normal_encoding latin1_encoding = {
00470   { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
00471   {
00472 #define BT_COLON BT_NMSTRT
00473 #include "asciitab.h"
00474 #undef BT_COLON
00475 #include "latin1tab.h"
00476   },
00477   STANDARD_VTABLE(sb_)
00478 };
00479 
00480 static void PTRCALL
00481 ascii_toUtf8(const ENCODING *enc,
00482              const char **fromP, const char *fromLim,
00483              char **toP, const char *toLim)
00484 {
00485   while (*fromP != fromLim && *toP != toLim)
00486     *(*toP)++ = *(*fromP)++;
00487 }
00488 
00489 #ifdef XML_NS
00490 
00491 static const struct normal_encoding ascii_encoding_ns = {
00492   { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
00493   {
00494 #include "asciitab.h"
00495 /* BT_NONXML == 0 */
00496   },
00497   STANDARD_VTABLE(sb_)
00498 };
00499 
00500 #endif
00501 
00502 static const struct normal_encoding ascii_encoding = {
00503   { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
00504   {
00505 #define BT_COLON BT_NMSTRT
00506 #include "asciitab.h"
00507 #undef BT_COLON
00508 /* BT_NONXML == 0 */
00509   },
00510   STANDARD_VTABLE(sb_)
00511 };
00512 
00513 static int PTRFASTCALL
00514 unicode_byte_type(char hi, char lo)
00515 {
00516   switch ((unsigned char)hi) {
00517   case 0xD8: case 0xD9: case 0xDA: case 0xDB:
00518     return BT_LEAD4;
00519   case 0xDC: case 0xDD: case 0xDE: case 0xDF:
00520     return BT_TRAIL;
00521   case 0xFF:
00522     switch ((unsigned char)lo) {
00523     case 0xFF:
00524     case 0xFE:
00525       return BT_NONXML;
00526     }
00527     break;
00528   }
00529   return BT_NONASCII;
00530 }
00531 
00532 #define DEFINE_UTF16_TO_UTF8(E) \
00533 static void  PTRCALL \
00534 E ## toUtf8(const ENCODING *enc, \
00535             const char **fromP, const char *fromLim, \
00536             char **toP, const char *toLim) \
00537 { \
00538   const char *from; \
00539   for (from = *fromP; from != fromLim; from += 2) { \
00540     int plane; \
00541     unsigned char lo2; \
00542     unsigned char lo = GET_LO(from); \
00543     unsigned char hi = GET_HI(from); \
00544     switch (hi) { \
00545     case 0: \
00546       if (lo < 0x80) { \
00547         if (*toP == toLim) { \
00548           *fromP = from; \
00549           return; \
00550         } \
00551         *(*toP)++ = lo; \
00552         break; \
00553       } \
00554       /* fall through */ \
00555     case 0x1: case 0x2: case 0x3: \
00556     case 0x4: case 0x5: case 0x6: case 0x7: \
00557       if (toLim -  *toP < 2) { \
00558         *fromP = from; \
00559         return; \
00560       } \
00561       *(*toP)++ = ((lo >> 6) | (hi << 2) |  UTF8_cval2); \
00562       *(*toP)++ = ((lo & 0x3f) | 0x80); \
00563       break; \
00564     default: \
00565       if (toLim -  *toP < 3)  { \
00566         *fromP = from; \
00567         return; \
00568       } \
00569       /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
00570       *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
00571       *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
00572       *(*toP)++ = ((lo & 0x3f) | 0x80); \
00573       break; \
00574     case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
00575       if (toLim -  *toP < 4) { \
00576         *fromP = from; \
00577         return; \
00578       } \
00579       plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
00580       *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
00581       *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
00582       from += 2; \
00583       lo2 = GET_LO(from); \
00584       *(*toP)++ = (((lo & 0x3) << 4) \
00585                    | ((GET_HI(from) & 0x3) << 2) \
00586                    | (lo2 >> 6) \
00587                    | 0x80); \
00588       *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
00589       break; \
00590     } \
00591   } \
00592   *fromP = from; \
00593 }
00594 
00595 #define DEFINE_UTF16_TO_UTF16(E) \
00596 static void  PTRCALL \
00597 E ## toUtf16(const ENCODING *enc, \
00598              const char **fromP, const char *fromLim, \
00599              unsigned short **toP, const unsigned short *toLim) \
00600 { \
00601   /* Avoid copying first half only of surrogate */ \
00602   if (fromLim - *fromP > ((toLim - *toP) << 1) \
00603       && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
00604     fromLim -= 2; \
00605   for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
00606     *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
00607 }
00608 
00609 #define SET2(ptr, ch) \
00610   (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
00611 #define GET_LO(ptr) ((unsigned char)(ptr)[0])
00612 #define GET_HI(ptr) ((unsigned char)(ptr)[1])
00613 
00614 DEFINE_UTF16_TO_UTF8(little2_)
00615 DEFINE_UTF16_TO_UTF16(little2_)
00616 
00617 #undef SET2
00618 #undef GET_LO
00619 #undef GET_HI
00620 
00621 #define SET2(ptr, ch) \
00622   (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
00623 #define GET_LO(ptr) ((unsigned char)(ptr)[1])
00624 #define GET_HI(ptr) ((unsigned char)(ptr)[0])
00625 
00626 DEFINE_UTF16_TO_UTF8(big2_)
00627 DEFINE_UTF16_TO_UTF16(big2_)
00628 
00629 #undef SET2
00630 #undef GET_LO
00631 #undef GET_HI
00632 
00633 #define LITTLE2_BYTE_TYPE(enc, p) \
00634  ((p)[1] == 0 \
00635   ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
00636   : unicode_byte_type((p)[1], (p)[0]))
00637 #define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
00638 #define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
00639 #define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
00640   UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
00641 #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
00642   UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
00643 
00644 #ifdef XML_MIN_SIZE
00645 
00646 static int PTRFASTCALL
00647 little2_byteType(const ENCODING *enc, const char *p)
00648 {
00649   return LITTLE2_BYTE_TYPE(enc, p);
00650 }
00651 
00652 static int PTRFASTCALL
00653 little2_byteToAscii(const ENCODING *enc, const char *p)
00654 {
00655   return LITTLE2_BYTE_TO_ASCII(enc, p);
00656 }
00657 
00658 static int PTRCALL
00659 little2_charMatches(const ENCODING *enc, const char *p, int c)
00660 {
00661   return LITTLE2_CHAR_MATCHES(enc, p, c);
00662 }
00663 
00664 static int PTRFASTCALL
00665 little2_isNameMin(const ENCODING *enc, const char *p)
00666 {
00667   return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
00668 }
00669 
00670 static int PTRFASTCALL
00671 little2_isNmstrtMin(const ENCODING *enc, const char *p)
00672 {
00673   return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
00674 }
00675 
00676 #undef VTABLE
00677 #define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
00678 
00679 #else /* not XML_MIN_SIZE */
00680 
00681 #undef PREFIX
00682 #define PREFIX(ident) little2_ ## ident
00683 #define MINBPC(enc) 2
00684 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
00685 #define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
00686 #define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
00687 #define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
00688 #define IS_NAME_CHAR(enc, p, n) 0
00689 #define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
00690 #define IS_NMSTRT_CHAR(enc, p, n) (0)
00691 #define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
00692 
00693 #include "xmltok_impl.c"
00694 
00695 #undef MINBPC
00696 #undef BYTE_TYPE
00697 #undef BYTE_TO_ASCII
00698 #undef CHAR_MATCHES
00699 #undef IS_NAME_CHAR
00700 #undef IS_NAME_CHAR_MINBPC
00701 #undef IS_NMSTRT_CHAR
00702 #undef IS_NMSTRT_CHAR_MINBPC
00703 #undef IS_INVALID_CHAR
00704 
00705 #endif /* not XML_MIN_SIZE */
00706 
00707 #ifdef XML_NS
00708 
00709 static const struct normal_encoding little2_encoding_ns = {
00710   { VTABLE, 2, 0,
00711 #if BYTEORDER == 1234
00712     1
00713 #else
00714     0
00715 #endif
00716   },
00717   {
00718 #include "asciitab.h"
00719 #include "latin1tab.h"
00720   },
00721   STANDARD_VTABLE(little2_)
00722 };
00723 
00724 #endif
00725 
00726 static const struct normal_encoding little2_encoding = {
00727   { VTABLE, 2, 0,
00728 #if BYTEORDER == 1234
00729     1
00730 #else
00731     0
00732 #endif
00733   },
00734   {
00735 #define BT_COLON BT_NMSTRT
00736 #include "asciitab.h"
00737 #undef BT_COLON
00738 #include "latin1tab.h"
00739   },
00740   STANDARD_VTABLE(little2_)
00741 };
00742 
00743 #if BYTEORDER != 4321
00744 
00745 #ifdef XML_NS
00746 
00747 static const struct normal_encoding internal_little2_encoding_ns = {
00748   { VTABLE, 2, 0, 1 },
00749   {
00750 #include "iasciitab.h"
00751 #include "latin1tab.h"
00752   },
00753   STANDARD_VTABLE(little2_)
00754 };
00755 
00756 #endif
00757 
00758 static const struct normal_encoding internal_little2_encoding = {
00759   { VTABLE, 2, 0, 1 },
00760   {
00761 #define BT_COLON BT_NMSTRT
00762 #include "iasciitab.h"
00763 #undef BT_COLON
00764 #include "latin1tab.h"
00765   },
00766   STANDARD_VTABLE(little2_)
00767 };
00768 
00769 #endif
00770 
00771 
00772 #define BIG2_BYTE_TYPE(enc, p) \
00773  ((p)[0] == 0 \
00774   ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
00775   : unicode_byte_type((p)[0], (p)[1]))
00776 #define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
00777 #define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
00778 #define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
00779   UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
00780 #define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
00781   UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
00782 
00783 #ifdef XML_MIN_SIZE
00784 
00785 static int PTRFASTCALL
00786 big2_byteType(const ENCODING *enc, const char *p)
00787 {
00788   return BIG2_BYTE_TYPE(enc, p);
00789 }
00790 
00791 static int PTRFASTCALL
00792 big2_byteToAscii(const ENCODING *enc, const char *p)
00793 {
00794   return BIG2_BYTE_TO_ASCII(enc, p);
00795 }
00796 
00797 static int PTRCALL
00798 big2_charMatches(const ENCODING *enc, const char *p, int c)
00799 {
00800   return BIG2_CHAR_MATCHES(enc, p, c);
00801 }
00802 
00803 static int PTRFASTCALL
00804 big2_isNameMin(const ENCODING *enc, const char *p)
00805 {
00806   return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
00807 }
00808 
00809 static int PTRFASTCALL
00810 big2_isNmstrtMin(const ENCODING *enc, const char *p)
00811 {
00812   return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
00813 }
00814 
00815 #undef VTABLE
00816 #define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
00817 
00818 #else /* not XML_MIN_SIZE */
00819 
00820 #undef PREFIX
00821 #define PREFIX(ident) big2_ ## ident
00822 #define MINBPC(enc) 2
00823 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
00824 #define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
00825 #define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
00826 #define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
00827 #define IS_NAME_CHAR(enc, p, n) 0
00828 #define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
00829 #define IS_NMSTRT_CHAR(enc, p, n) (0)
00830 #define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
00831 
00832 #include "xmltok_impl.c"
00833 
00834 #undef MINBPC
00835 #undef BYTE_TYPE
00836 #undef BYTE_TO_ASCII
00837 #undef CHAR_MATCHES
00838 #undef IS_NAME_CHAR
00839 #undef IS_NAME_CHAR_MINBPC
00840 #undef IS_NMSTRT_CHAR
00841 #undef IS_NMSTRT_CHAR_MINBPC
00842 #undef IS_INVALID_CHAR
00843 
00844 #endif /* not XML_MIN_SIZE */
00845 
00846 #ifdef XML_NS
00847 
00848 static const struct normal_encoding big2_encoding_ns = {
00849   { VTABLE, 2, 0,
00850 #if BYTEORDER == 4321
00851   1
00852 #else
00853   0
00854 #endif
00855   },
00856   {
00857 #include "asciitab.h"
00858 #include "latin1tab.h"
00859   },
00860   STANDARD_VTABLE(big2_)
00861 };
00862 
00863 #endif
00864 
00865 static const struct normal_encoding big2_encoding = {
00866   { VTABLE, 2, 0,
00867 #if BYTEORDER == 4321
00868   1
00869 #else
00870   0
00871 #endif
00872   },
00873   {
00874 #define BT_COLON BT_NMSTRT
00875 #include "asciitab.h"
00876 #undef BT_COLON
00877 #include "latin1tab.h"
00878   },
00879   STANDARD_VTABLE(big2_)
00880 };
00881 
00882 #if BYTEORDER != 1234
00883 
00884 #ifdef XML_NS
00885 
00886 static const struct normal_encoding internal_big2_encoding_ns = {
00887   { VTABLE, 2, 0, 1 },
00888   {
00889 #include "iasciitab.h"
00890 #include "latin1tab.h"
00891   },
00892   STANDARD_VTABLE(big2_)
00893 };
00894 
00895 #endif
00896 
00897 static const struct normal_encoding internal_big2_encoding = {
00898   { VTABLE, 2, 0, 1 },
00899   {
00900 #define BT_COLON BT_NMSTRT
00901 #include "iasciitab.h"
00902 #undef BT_COLON
00903 #include "latin1tab.h"
00904   },
00905   STANDARD_VTABLE(big2_)
00906 };
00907 
00908 #endif
00909 
00910 #undef PREFIX
00911 
00912 static int FASTCALL
00913 streqci(const char *s1, const char *s2)
00914 {
00915   for (;;) {
00916     char c1 = *s1++;
00917     char c2 = *s2++;
00918     if (ASCII_a <= c1 && c1 <= ASCII_z)
00919       c1 += ASCII_A - ASCII_a;
00920     if (ASCII_a <= c2 && c2 <= ASCII_z)
00921       c2 += ASCII_A - ASCII_a;
00922     if (c1 != c2)
00923       return 0;
00924     if (!c1)
00925       break;
00926   }
00927   return 1;
00928 }
00929 
00930 static void PTRCALL
00931 initUpdatePosition(const ENCODING *enc, const char *ptr,
00932                    const char *end, POSITION *pos)
00933 {
00934   normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
00935 }
00936 
00937 static int
00938 toAscii(const ENCODING *enc, const char *ptr, const char *end)
00939 {
00940   char buf[1];
00941   char *p = buf;
00942   XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
00943   if (p == buf)
00944     return -1;
00945   else
00946     return buf[0];
00947 }
00948 
00949 static int FASTCALL
00950 isSpace(int c)
00951 {
00952   switch (c) {
00953   case 0x20:
00954   case 0xD:
00955   case 0xA:
00956   case 0x9:
00957     return 1;
00958   }
00959   return 0;
00960 }
00961 
00962 /* Return 1 if there's just optional white space or there's an S
00963    followed by name=val.
00964 */
00965 static int
00966 parsePseudoAttribute(const ENCODING *enc,
00967                      const char *ptr,
00968                      const char *end,
00969                      const char **namePtr,
00970                      const char **nameEndPtr,
00971                      const char **valPtr,
00972                      const char **nextTokPtr)
00973 {
00974   int c;
00975   char open;
00976   if (ptr == end) {
00977     *namePtr = NULL;
00978     return 1;
00979   }
00980   if (!isSpace(toAscii(enc, ptr, end))) {
00981     *nextTokPtr = ptr;
00982     return 0;
00983   }
00984   do {
00985     ptr += enc->minBytesPerChar;
00986   } while (isSpace(toAscii(enc, ptr, end)));
00987   if (ptr == end) {
00988     *namePtr = NULL;
00989     return 1;
00990   }
00991   *namePtr = ptr;
00992   for (;;) {
00993     c = toAscii(enc, ptr, end);
00994     if (c == -1) {
00995       *nextTokPtr = ptr;
00996       return 0;
00997     }
00998     if (c == ASCII_EQUALS) {
00999       *nameEndPtr = ptr;
01000       break;
01001     }
01002     if (isSpace(c)) {
01003       *nameEndPtr = ptr;
01004       do {
01005         ptr += enc->minBytesPerChar;
01006       } while (isSpace(c = toAscii(enc, ptr, end)));
01007       if (c != ASCII_EQUALS) {
01008         *nextTokPtr = ptr;
01009         return 0;
01010       }
01011       break;
01012     }
01013     ptr += enc->minBytesPerChar;
01014   }
01015   if (ptr == *namePtr) {
01016     *nextTokPtr = ptr;
01017     return 0;
01018   }
01019   ptr += enc->minBytesPerChar;
01020   c = toAscii(enc, ptr, end);
01021   while (isSpace(c)) {
01022     ptr += enc->minBytesPerChar;
01023     c = toAscii(enc, ptr, end);
01024   }
01025   if (c != ASCII_QUOT && c != ASCII_APOS) {
01026     *nextTokPtr = ptr;
01027     return 0;
01028   }
01029   open = (char)c;
01030   ptr += enc->minBytesPerChar;
01031   *valPtr = ptr;
01032   for (;; ptr += enc->minBytesPerChar) {
01033     c = toAscii(enc, ptr, end);
01034     if (c == open)
01035       break;
01036     if (!(ASCII_a <= c && c <= ASCII_z)
01037         && !(ASCII_A <= c && c <= ASCII_Z)
01038         && !(ASCII_0 <= c && c <= ASCII_9)
01039         && c != ASCII_PERIOD
01040         && c != ASCII_MINUS
01041         && c != ASCII_UNDERSCORE) {
01042       *nextTokPtr = ptr;
01043       return 0;
01044     }
01045   }
01046   *nextTokPtr = ptr + enc->minBytesPerChar;
01047   return 1;
01048 }
01049 
01050 static const char KW_version[] = {
01051   ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
01052 };
01053 
01054 static const char KW_encoding[] = {
01055   ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
01056 };
01057 
01058 static const char KW_standalone[] = {
01059   ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o,
01060   ASCII_n, ASCII_e, '\0'
01061 };
01062 
01063 static const char KW_yes[] = {
01064   ASCII_y, ASCII_e, ASCII_s,  '\0'
01065 };
01066 
01067 static const char KW_no[] = {
01068   ASCII_n, ASCII_o,  '\0'
01069 };
01070 
01071 static int
01072 doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
01073                                                  const char *,
01074                                                  const char *),
01075                int isGeneralTextEntity,
01076                const ENCODING *enc,
01077                const char *ptr,
01078                const char *end,
01079                const char **badPtr,
01080                const char **versionPtr,
01081                const char **versionEndPtr,
01082                const char **encodingName,
01083                const ENCODING **encoding,
01084                int *standalone)
01085 {
01086   const char *val = NULL;
01087   const char *name = NULL;
01088   const char *nameEnd = NULL;
01089   ptr += 5 * enc->minBytesPerChar;
01090   end -= 2 * enc->minBytesPerChar;
01091   if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
01092       || !name) {
01093     *badPtr = ptr;
01094     return 0;
01095   }
01096   if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
01097     if (!isGeneralTextEntity) {
01098       *badPtr = name;
01099       return 0;
01100     }
01101   }
01102   else {
01103     if (versionPtr)
01104       *versionPtr = val;
01105     if (versionEndPtr)
01106       *versionEndPtr = ptr;
01107     if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
01108       *badPtr = ptr;
01109       return 0;
01110     }
01111     if (!name) {
01112       if (isGeneralTextEntity) {
01113         /* a TextDecl must have an EncodingDecl */
01114         *badPtr = ptr;
01115         return 0;
01116       }
01117       return 1;
01118     }
01119   }
01120   if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
01121     int c = toAscii(enc, val, end);
01122     if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
01123       *badPtr = val;
01124       return 0;
01125     }
01126     if (encodingName)
01127       *encodingName = val;
01128     if (encoding)
01129       *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
01130     if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
01131       *badPtr = ptr;
01132       return 0;
01133     }
01134     if (!name)
01135       return 1;
01136   }
01137   if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
01138       || isGeneralTextEntity) {
01139     *badPtr = name;
01140     return 0;
01141   }
01142   if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
01143     if (standalone)
01144       *standalone = 1;
01145   }
01146   else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
01147     if (standalone)
01148       *standalone = 0;
01149   }
01150   else {
01151     *badPtr = val;
01152     return 0;
01153   }
01154   while (isSpace(toAscii(enc, ptr, end)))
01155     ptr += enc->minBytesPerChar;
01156   if (ptr != end) {
01157     *badPtr = ptr;
01158     return 0;
01159   }
01160   return 1;
01161 }
01162 
01163 static int FASTCALL
01164 checkCharRefNumber(int result)
01165 {
01166   switch (result >> 8) {
01167   case 0xD8: case 0xD9: case 0xDA: case 0xDB:
01168   case 0xDC: case 0xDD: case 0xDE: case 0xDF:
01169     return -1;
01170   case 0:
01171     if (latin1_encoding.type[result] == BT_NONXML)
01172       return -1;
01173     break;
01174   case 0xFF:
01175     if (result == 0xFFFE || result == 0xFFFF)
01176       return -1;
01177     break;
01178   }
01179   return result;
01180 }
01181 
01182 int FASTCALL
01183 XmlUtf8Encode(int c, char *buf)
01184 {
01185   enum {
01186     /* minN is minimum legal resulting value for N byte sequence */
01187     min2 = 0x80,
01188     min3 = 0x800,
01189     min4 = 0x10000
01190   };
01191 
01192   if (c < 0)
01193     return 0;
01194   if (c < min2) {
01195     buf[0] = (char)(c | UTF8_cval1);
01196     return 1;
01197   }
01198   if (c < min3) {
01199     buf[0] = (char)((c >> 6) | UTF8_cval2);
01200     buf[1] = (char)((c & 0x3f) | 0x80);
01201     return 2;
01202   }
01203   if (c < min4) {
01204     buf[0] = (char)((c >> 12) | UTF8_cval3);
01205     buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
01206     buf[2] = (char)((c & 0x3f) | 0x80);
01207     return 3;
01208   }
01209   if (c < 0x110000) {
01210     buf[0] = (char)((c >> 18) | UTF8_cval4);
01211     buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
01212     buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
01213     buf[3] = (char)((c & 0x3f) | 0x80);
01214     return 4;
01215   }
01216   return 0;
01217 }
01218 
01219 int FASTCALL
01220 XmlUtf16Encode(int charNum, unsigned short *buf)
01221 {
01222   if (charNum < 0)
01223     return 0;
01224   if (charNum < 0x10000) {
01225     buf[0] = (unsigned short)charNum;
01226     return 1;
01227   }
01228   if (charNum < 0x110000) {
01229     charNum -= 0x10000;
01230     buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
01231     buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
01232     return 2;
01233   }
01234   return 0;
01235 }
01236 
01237 struct unknown_encoding {
01238   struct normal_encoding normal;
01239   CONVERTER convert;
01240   void *userData;
01241   unsigned short utf16[256];
01242   char utf8[256][4];
01243 };
01244 
01245 #define AS_UNKNOWN_ENCODING(enc)  ((const struct unknown_encoding *) (enc))
01246 
01247 int
01248 XmlSizeOfUnknownEncoding(void)
01249 {
01250   return sizeof(struct unknown_encoding);
01251 }
01252 
01253 static int PTRFASTCALL
01254 unknown_isName(const ENCODING *enc, const char *p)
01255 {
01256   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
01257   int c = uenc->convert(uenc->userData, p);
01258   if (c & ~0xFFFF)
01259     return 0;
01260   return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
01261 }
01262 
01263 static int PTRFASTCALL
01264 unknown_isNmstrt(const ENCODING *enc, const char *p)
01265 {
01266   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
01267   int c = uenc->convert(uenc->userData, p);
01268   if (c & ~0xFFFF)
01269     return 0;
01270   return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
01271 }
01272 
01273 static int PTRFASTCALL
01274 unknown_isInvalid(<