xref: /freebsd/contrib/expat/lib/xmltok.c (revision c7b67985633c408cae69703ca443cbfd84d326a8)
1 /*
2                             __  __            _
3                          ___\ \/ /_ __   __ _| |_
4                         / _ \\  /| '_ \ / _` | __|
5                        |  __//  \| |_) | (_| | |_
6                         \___/_/\_\ .__/ \__,_|\__|
7                                  |_| XML parser
8 
9    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10    Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
11    Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
12    Copyright (c) 2002      Greg Stein <gstein@users.sourceforge.net>
13    Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
14    Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
15    Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
16    Copyright (c) 2016      Pascal Cuoq <cuoq@trust-in-soft.com>
17    Copyright (c) 2016      Don Lewis <truckman@apache.org>
18    Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
19    Copyright (c) 2017      Alexander Bluhm <alexander.bluhm@gmx.net>
20    Copyright (c) 2017      Benbuck Nason <bnason@netflix.com>
21    Copyright (c) 2017      José Gutiérrez de la Concha <jose@zeroc.com>
22    Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
23    Copyright (c) 2021      Donghee Na <donghee.na@python.org>
24    Copyright (c) 2022      Martin Ettl <ettl.martin78@googlemail.com>
25    Copyright (c) 2022      Sean McBride <sean@rogue-research.com>
26    Copyright (c) 2023      Hanno Böck <hanno@gentoo.org>
27    Copyright (c) 2025      Alfonso Gregory <gfunni234@gmail.com>
28    Copyright (c) 2026      Nick Begg <nick@stunttruck.net>
29    Copyright (c) 2026      Kartik Kenchi <netliomax25@gmail.com>
30    Copyright (c) 2026      Afonso Januário <afonso-januario@hotmail.com>
31    Licensed under the MIT license:
32 
33    Permission is  hereby granted,  free of charge,  to any  person obtaining
34    a  copy  of  this  software   and  associated  documentation  files  (the
35    "Software"),  to  deal in  the  Software  without restriction,  including
36    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
37    distribute, sublicense, and/or sell copies of the Software, and to permit
38    persons  to whom  the Software  is  furnished to  do so,  subject to  the
39    following conditions:
40 
41    The above copyright  notice and this permission notice  shall be included
42    in all copies or substantial portions of the Software.
43 
44    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
45    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
46    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
47    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
48    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
49    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
50    USE OR OTHER DEALINGS IN THE SOFTWARE.
51 
52    SPDX-License-Identifier: MIT
53 */
54 
55 #include "expat_config.h"
56 
57 #include <stddef.h>
58 #include <string.h> /* memcpy */
59 #include <stdbool.h>
60 
61 #ifdef _WIN32
62 #  include "winconfig.h"
63 #endif
64 
65 #include "internal.h"
66 #include "fallthrough.h"
67 #include "xmltok.h"
68 #include "nametab.h"
69 
70 #ifdef XML_DTD
71 #  define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
72 #else
73 #  define IGNORE_SECTION_TOK_VTABLE /* as nothing */
74 #endif
75 
76 #define VTABLE1                                                                \
77   {PREFIX(prologTok), PREFIX(contentTok),                                      \
78    PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE},                         \
79       {PREFIX(attributeValueTok), PREFIX(entityValueTok)},                     \
80       PREFIX(nameMatchesAscii), PREFIX(nameLength), PREFIX(skipS),             \
81       PREFIX(getAtts), PREFIX(charRefNumber), PREFIX(predefinedEntityName),    \
82       PREFIX(updatePosition), PREFIX(isPublicId)
83 
84 #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
85 
86 #define UCS2_GET_NAMING(pages, hi, lo)                                         \
87   (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1u << ((lo) & 0x1F)))
88 
89 /* A 2 byte UTF-8 representation splits the characters 11 bits between
90    the bottom 5 and 6 bits of the bytes.  We need 8 bits to index into
91    pages, 3 bits to add to that index and 5 bits to generate the mask.
92 */
93 #define UTF8_GET_NAMING2(pages, byte)                                          \
94   (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
95                 + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
96    & (1u << (((byte)[1]) & 0x1F)))
97 
98 /* A 3 byte UTF-8 representation splits the characters 16 bits between
99    the bottom 4, 6 and 6 bits of the bytes.  We need 8 bits to index
100    into pages, 3 bits to add to that index and 5 bits to generate the
101    mask.
102 */
103 #define UTF8_GET_NAMING3(pages, byte)                                          \
104   (namingBitmap                                                                \
105        [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
106          << 3)                                                                 \
107         + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
108    & (1u << (((byte)[2]) & 0x1F)))
109 
110 /* Detection of invalid UTF-8 sequences is based on Table 3.1B
111    of Unicode 3.2: https://www.unicode.org/unicode/reports/tr28/
112    with the additional restriction of not allowing the Unicode
113    code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE).
114    Implementation details:
115      (A & 0x80) == 0     means A < 0x80
116    and
117      (A & 0xC0) == 0xC0  means A > 0xBF
118 */
119 
120 #define UTF8_INVALID2(p)                                                       \
121   ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
122 
123 #define UTF8_INVALID3(p)                                                       \
124   (((p)[2] & 0x80) == 0                                                        \
125    || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
126                                       : ((p)[2] & 0xC0) == 0xC0)               \
127    || ((*p) == 0xE0                                                            \
128            ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
129            : ((p)[1] & 0x80) == 0                                              \
130                  || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
131 
132 #define UTF8_INVALID4(p)                                                       \
133   (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
134    || ((p)[2] & 0xC0) == 0xC0                                                  \
135    || ((*p) == 0xF0                                                            \
136            ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
137            : ((p)[1] & 0x80) == 0                                              \
138                  || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
139 
140 static int
141 isNever(const ENCODING *enc, const char *p) {
142   UNUSED_P(enc);
143   UNUSED_P(p);
144   return 0;
145 }
146 
147 static int
148 utf8_isName2(const ENCODING *enc, const char *p) {
149   UNUSED_P(enc);
150   return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
151 }
152 
153 static int
154 utf8_isName3(const ENCODING *enc, const char *p) {
155   UNUSED_P(enc);
156   return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
157 }
158 
159 #define utf8_isName4 isNever
160 
161 static int
162 utf8_isNmstrt2(const ENCODING *enc, const char *p) {
163   UNUSED_P(enc);
164   return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
165 }
166 
167 static int
168 utf8_isNmstrt3(const ENCODING *enc, const char *p) {
169   UNUSED_P(enc);
170   return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
171 }
172 
173 #define utf8_isNmstrt4 isNever
174 
175 static int
176 utf8_isInvalid2(const ENCODING *enc, const char *p) {
177   UNUSED_P(enc);
178   return UTF8_INVALID2((const unsigned char *)p);
179 }
180 
181 static int
182 utf8_isInvalid3(const ENCODING *enc, const char *p) {
183   UNUSED_P(enc);
184   return UTF8_INVALID3((const unsigned char *)p);
185 }
186 
187 static int
188 utf8_isInvalid4(const ENCODING *enc, const char *p) {
189   UNUSED_P(enc);
190   return UTF8_INVALID4((const unsigned char *)p);
191 }
192 
193 struct normal_encoding {
194   ENCODING enc;
195   unsigned char type[256];
196 #ifdef XML_MIN_SIZE
197   int (*byteType)(const ENCODING *, const char *);
198   int (*isNameMin)(const ENCODING *, const char *);
199   int (*isNmstrtMin)(const ENCODING *, const char *);
200   int (*byteToAscii)(const ENCODING *, const char *);
201   int (*charMatches)(const ENCODING *, const char *, int);
202 #endif /* XML_MIN_SIZE */
203   int (*isName2)(const ENCODING *, const char *);
204   int (*isName3)(const ENCODING *, const char *);
205   int (*isName4)(const ENCODING *, const char *);
206   int (*isNmstrt2)(const ENCODING *, const char *);
207   int (*isNmstrt3)(const ENCODING *, const char *);
208   int (*isNmstrt4)(const ENCODING *, const char *);
209   int (*isInvalid2)(const ENCODING *, const char *);
210   int (*isInvalid3)(const ENCODING *, const char *);
211   int (*isInvalid4)(const ENCODING *, const char *);
212 };
213 
214 #define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc))
215 
216 #ifdef XML_MIN_SIZE
217 
218 #  define STANDARD_VTABLE(E)                                                   \
219     E##byteType, E##isNameMin, E##isNmstrtMin, E##byteToAscii, E##charMatches,
220 
221 #else
222 
223 #  define STANDARD_VTABLE(E) /* as nothing */
224 
225 #endif
226 
227 #define NORMAL_VTABLE(E)                                                       \
228   E##isName2, E##isName3, E##isName4, E##isNmstrt2, E##isNmstrt3,              \
229       E##isNmstrt4, E##isInvalid2, E##isInvalid3, E##isInvalid4
230 
231 #define NULL_VTABLE                                                            \
232   /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL,                  \
233       /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL,        \
234       /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL
235 
236 /* Like NULL_VTABLE but with a real isInvalid4 so the UTF-16 encodings reject a
237    high surrogate that is not followed by a low surrogate.  Only needed for the
238    XML_MIN_SIZE build, where the shared tokenizer dispatches through the vtable;
239    the regular build inlines the same check via IS_INVALID_CHAR. */
240 #ifdef XML_MIN_SIZE
241 #  define UTF16_NULL_VTABLE(E)                                                 \
242     /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL,                \
243         /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL,      \
244         /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, E##isInvalid4
245 #else
246 #  define UTF16_NULL_VTABLE(E) NULL_VTABLE
247 #endif
248 
249 static int checkCharRefNumber(int result);
250 
251 #include "xmltok_impl.h"
252 #include "ascii.h"
253 
254 #ifdef XML_MIN_SIZE
255 #  define sb_isNameMin isNever
256 #  define sb_isNmstrtMin isNever
257 #endif
258 
259 #ifdef XML_MIN_SIZE
260 #  define MINBPC(enc) ((enc)->minBytesPerChar)
261 #else
262 /* minimum bytes per character */
263 #  define MINBPC(enc) 1
264 #endif
265 
266 #define SB_BYTE_TYPE(enc, p)                                                   \
267   (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
268 
269 #ifdef XML_MIN_SIZE
270 static int
271 sb_byteType(const ENCODING *enc, const char *p) {
272   return SB_BYTE_TYPE(enc, p);
273 }
274 #  define BYTE_TYPE(enc, p) (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
275 #else
276 #  define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
277 #endif
278 
279 #ifdef XML_MIN_SIZE
280 #  define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
281 static int
282 sb_byteToAscii(const ENCODING *enc, const char *p) {
283   UNUSED_P(enc);
284   return *p;
285 }
286 #else
287 #  define BYTE_TO_ASCII(enc, p) (*(p))
288 #endif
289 
290 #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
291 #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
292 #ifdef XML_MIN_SIZE
293 #  define IS_INVALID_CHAR(enc, p, n)                                           \
294     (AS_NORMAL_ENCODING(enc)->isInvalid##n                                     \
295      && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
296 #else
297 #  define IS_INVALID_CHAR(enc, p, n)                                           \
298     (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
299 #endif
300 
301 #ifdef XML_MIN_SIZE
302 #  define IS_NAME_CHAR_MINBPC(enc, p)                                          \
303     (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
304 #  define IS_NMSTRT_CHAR_MINBPC(enc, p)                                        \
305     (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
306 #else
307 #  define IS_NAME_CHAR_MINBPC(enc, p) (0)
308 #  define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
309 #endif
310 
311 #ifdef XML_MIN_SIZE
312 #  define CHAR_MATCHES(enc, p, c)                                              \
313     (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
314 static int
315 sb_charMatches(const ENCODING *enc, const char *p, int c) {
316   UNUSED_P(enc);
317   return *p == c;
318 }
319 #else
320 /* c is an ASCII character */
321 #  define CHAR_MATCHES(enc, p, c) (*(p) == (c))
322 #endif
323 
324 #define PREFIX(ident) normal_##ident
325 #define XML_TOK_IMPL_C
326 #include "xmltok_impl.c"
327 #undef XML_TOK_IMPL_C
328 
329 #undef MINBPC
330 #undef BYTE_TYPE
331 #undef BYTE_TO_ASCII
332 #undef CHAR_MATCHES
333 #undef IS_NAME_CHAR
334 #undef IS_NAME_CHAR_MINBPC
335 #undef IS_NMSTRT_CHAR
336 #undef IS_NMSTRT_CHAR_MINBPC
337 #undef IS_INVALID_CHAR
338 
339 enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
340        UTF8_cval1 = 0x00,
341        UTF8_cval2 = 0xc0,
342        UTF8_cval3 = 0xe0,
343        UTF8_cval4 = 0xf0
344 };
345 
346 void
347 _INTERNAL_trim_to_complete_utf8_characters(const char *from,
348                                            const char **fromLimRef) {
349   const char *fromLim = *fromLimRef;
350   size_t walked = 0;
351   for (; fromLim > from; fromLim--, walked++) {
352     const unsigned char prev = (unsigned char)fromLim[-1];
353     if ((prev & 0xf8u)
354         == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
355       if (walked + 1 >= 4) {
356         fromLim += 4 - 1;
357         break;
358       } else {
359         walked = 0;
360       }
361     } else if ((prev & 0xf0u)
362                == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
363       if (walked + 1 >= 3) {
364         fromLim += 3 - 1;
365         break;
366       } else {
367         walked = 0;
368       }
369     } else if ((prev & 0xe0u)
370                == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
371       if (walked + 1 >= 2) {
372         fromLim += 2 - 1;
373         break;
374       } else {
375         walked = 0;
376       }
377     } else if ((prev & 0x80u)
378                == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
379       break;
380     }
381   }
382   *fromLimRef = fromLim;
383 }
384 
385 static enum XML_Convert_Result
386 utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
387             char **toP, const char *toLim) {
388   bool input_incomplete = false;
389   bool output_exhausted = false;
390 
391   /* Avoid copying partial characters (due to limited space). */
392   const ptrdiff_t bytesAvailable = fromLim - *fromP;
393   const ptrdiff_t bytesStorable = toLim - *toP;
394   UNUSED_P(enc);
395   if (bytesAvailable > bytesStorable) {
396     fromLim = *fromP + bytesStorable;
397     output_exhausted = true;
398   }
399 
400   /* Avoid copying partial characters (from incomplete input). */
401   {
402     const char *const fromLimBefore = fromLim;
403     _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
404     if (fromLim < fromLimBefore) {
405       input_incomplete = true;
406     }
407   }
408 
409   {
410     const ptrdiff_t bytesToCopy = fromLim - *fromP;
411     memcpy(*toP, *fromP, bytesToCopy);
412     *fromP += bytesToCopy;
413     *toP += bytesToCopy;
414   }
415 
416   if (output_exhausted) /* needs to go first */
417     return XML_CONVERT_OUTPUT_EXHAUSTED;
418   else if (input_incomplete)
419     return XML_CONVERT_INPUT_INCOMPLETE;
420   else
421     return XML_CONVERT_COMPLETED;
422 }
423 
424 static enum XML_Convert_Result
425 utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
426              unsigned short **toP, const unsigned short *toLim) {
427   enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
428   unsigned short *to = *toP;
429   const char *from = *fromP;
430   while (from < fromLim && to < toLim) {
431     switch (SB_BYTE_TYPE(enc, from)) {
432     case BT_LEAD2:
433       if (fromLim - from < 2) {
434         res = XML_CONVERT_INPUT_INCOMPLETE;
435         goto after;
436       }
437       *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
438       from += 2;
439       break;
440     case BT_LEAD3:
441       if (fromLim - from < 3) {
442         res = XML_CONVERT_INPUT_INCOMPLETE;
443         goto after;
444       }
445       *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6)
446                                | (from[2] & 0x3f));
447       from += 3;
448       break;
449     case BT_LEAD4: {
450       unsigned long n;
451       if (toLim - to < 2) {
452         res = XML_CONVERT_OUTPUT_EXHAUSTED;
453         goto after;
454       }
455       if (fromLim - from < 4) {
456         res = XML_CONVERT_INPUT_INCOMPLETE;
457         goto after;
458       }
459       n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
460           | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
461       n -= 0x10000;
462       to[0] = (unsigned short)((n >> 10) | 0xD800);
463       to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
464       to += 2;
465       from += 4;
466     } break;
467     default:
468       *to++ = *from++;
469       break;
470     }
471   }
472   if (from < fromLim)
473     res = XML_CONVERT_OUTPUT_EXHAUSTED;
474 after:
475   *fromP = from;
476   *toP = to;
477   return res;
478 }
479 
480 #ifdef XML_NS
481 static const struct normal_encoding utf8_encoding_ns
482     = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
483        {
484 #  include "asciitab.h"
485 #  include "utf8tab.h"
486        },
487        STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
488 #endif
489 
490 static const struct normal_encoding utf8_encoding
491     = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
492        {
493 #define BT_COLON BT_NMSTRT
494 #include "asciitab.h"
495 #undef BT_COLON
496 #include "utf8tab.h"
497        },
498        STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
499 
500 #ifdef XML_NS
501 
502 static const struct normal_encoding internal_utf8_encoding_ns
503     = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
504        {
505 #  include "iasciitab.h"
506 #  include "utf8tab.h"
507        },
508        STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
509 
510 #endif
511 
512 static const struct normal_encoding internal_utf8_encoding
513     = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
514        {
515 #define BT_COLON BT_NMSTRT
516 #include "iasciitab.h"
517 #undef BT_COLON
518 #include "utf8tab.h"
519        },
520        STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
521 
522 static enum XML_Convert_Result
523 latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
524               char **toP, const char *toLim) {
525   UNUSED_P(enc);
526   for (;;) {
527     unsigned char c;
528     if (*fromP == fromLim)
529       return XML_CONVERT_COMPLETED;
530     c = (unsigned char)**fromP;
531     if (c & 0x80) {
532       if (toLim - *toP < 2)
533         return XML_CONVERT_OUTPUT_EXHAUSTED;
534       *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
535       *(*toP)++ = (char)((c & 0x3f) | 0x80);
536       (*fromP)++;
537     } else {
538       if (*toP == toLim)
539         return XML_CONVERT_OUTPUT_EXHAUSTED;
540       *(*toP)++ = *(*fromP)++;
541     }
542   }
543 }
544 
545 static enum XML_Convert_Result
546 latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
547                unsigned short **toP, const unsigned short *toLim) {
548   UNUSED_P(enc);
549   while (*fromP < fromLim && *toP < toLim)
550     *(*toP)++ = (unsigned char)*(*fromP)++;
551 
552   if ((*toP == toLim) && (*fromP < fromLim))
553     return XML_CONVERT_OUTPUT_EXHAUSTED;
554   else
555     return XML_CONVERT_COMPLETED;
556 }
557 
558 #ifdef XML_NS
559 
560 static const struct normal_encoding latin1_encoding_ns
561     = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
562        {
563 #  include "asciitab.h"
564 #  include "latin1tab.h"
565        },
566        STANDARD_VTABLE(sb_) NULL_VTABLE};
567 
568 #endif
569 
570 static const struct normal_encoding latin1_encoding
571     = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
572        {
573 #define BT_COLON BT_NMSTRT
574 #include "asciitab.h"
575 #undef BT_COLON
576 #include "latin1tab.h"
577        },
578        STANDARD_VTABLE(sb_) NULL_VTABLE};
579 
580 static enum XML_Convert_Result
581 ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
582              char **toP, const char *toLim) {
583   UNUSED_P(enc);
584   while (*fromP < fromLim && *toP < toLim)
585     *(*toP)++ = *(*fromP)++;
586 
587   if ((*toP == toLim) && (*fromP < fromLim))
588     return XML_CONVERT_OUTPUT_EXHAUSTED;
589   else
590     return XML_CONVERT_COMPLETED;
591 }
592 
593 #ifdef XML_NS
594 
595 static const struct normal_encoding ascii_encoding_ns
596     = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
597        {
598 #  include "asciitab.h"
599            /* BT_NONXML == 0 */
600        },
601        STANDARD_VTABLE(sb_) NULL_VTABLE};
602 
603 #endif
604 
605 static const struct normal_encoding ascii_encoding
606     = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
607        {
608 #define BT_COLON BT_NMSTRT
609 #include "asciitab.h"
610 #undef BT_COLON
611            /* BT_NONXML == 0 */
612        },
613        STANDARD_VTABLE(sb_) NULL_VTABLE};
614 
615 static int
616 unicode_byte_type(char hi, char lo) {
617   switch ((unsigned char)hi) {
618   /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
619   case 0xD8:
620   case 0xD9:
621   case 0xDA:
622   case 0xDB:
623     return BT_LEAD4;
624   /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
625   case 0xDC:
626   case 0xDD:
627   case 0xDE:
628   case 0xDF:
629     return BT_TRAIL;
630   case 0xFF:
631     switch ((unsigned char)lo) {
632     case 0xFF: /* noncharacter-FFFF */
633     case 0xFE: /* noncharacter-FFFE */
634       return BT_NONXML;
635     }
636     break;
637   }
638   return BT_NONASCII;
639 }
640 
641 #define DEFINE_UTF16_TO_UTF8(E)                                                \
642   static enum XML_Convert_Result E##toUtf8(                                    \
643       const ENCODING *enc, const char **fromP, const char *fromLim,            \
644       char **toP, const char *toLim) {                                         \
645     const char *from = *fromP;                                                 \
646     UNUSED_P(enc);                                                             \
647     fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
648     for (; from < fromLim; from += 2) {                                        \
649       int plane;                                                               \
650       unsigned char lo2;                                                       \
651       unsigned char lo = GET_LO(from);                                         \
652       unsigned char hi = GET_HI(from);                                         \
653       switch (hi) {                                                            \
654       case 0:                                                                  \
655         if (lo < 0x80) {                                                       \
656           if (*toP == toLim) {                                                 \
657             *fromP = from;                                                     \
658             return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
659           }                                                                    \
660           *(*toP)++ = lo;                                                      \
661           break;                                                               \
662         }                                                                      \
663         EXPAT_FALLTHROUGH;                                                     \
664       case 0x1:                                                                \
665       case 0x2:                                                                \
666       case 0x3:                                                                \
667       case 0x4:                                                                \
668       case 0x5:                                                                \
669       case 0x6:                                                                \
670       case 0x7:                                                                \
671         if (toLim - *toP < 2) {                                                \
672           *fromP = from;                                                       \
673           return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
674         }                                                                      \
675         *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
676         *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
677         break;                                                                 \
678       default:                                                                 \
679         if (toLim - *toP < 3) {                                                \
680           *fromP = from;                                                       \
681           return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
682         }                                                                      \
683         /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
684         *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
685         *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
686         *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
687         break;                                                                 \
688       case 0xD8:                                                               \
689       case 0xD9:                                                               \
690       case 0xDA:                                                               \
691       case 0xDB:                                                               \
692         if (toLim - *toP < 4) {                                                \
693           *fromP = from;                                                       \
694           return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
695         }                                                                      \
696         if (fromLim - from < 4) {                                              \
697           *fromP = from;                                                       \
698           return XML_CONVERT_INPUT_INCOMPLETE;                                 \
699         }                                                                      \
700         plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
701         *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
702         *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
703         from += 2;                                                             \
704         lo2 = GET_LO(from);                                                    \
705         *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
706                      | (lo2 >> 6) | 0x80);                                     \
707         *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
708         break;                                                                 \
709       }                                                                        \
710     }                                                                          \
711     *fromP = from;                                                             \
712     if (from < fromLim)                                                        \
713       return XML_CONVERT_INPUT_INCOMPLETE;                                     \
714     else                                                                       \
715       return XML_CONVERT_COMPLETED;                                            \
716   }
717 
718 #define DEFINE_UTF16_TO_UTF16(E)                                               \
719   static enum XML_Convert_Result E##toUtf16(                                   \
720       const ENCODING *enc, const char **fromP, const char *fromLim,            \
721       unsigned short **toP, const unsigned short *toLim) {                     \
722     enum XML_Convert_Result res = XML_CONVERT_COMPLETED;                       \
723     UNUSED_P(enc);                                                             \
724     fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */  \
725     /* Avoid copying the first half (2 bytes) of surrogate pairs (4 bytes) */  \
726     if (fromLim - *fromP > ((toLim - *toP) << 1)                               \
727         && /* are the last two bytes a high surrogate (0xD800-0xDBFF)? */      \
728         (GET_HI(fromLim - 2) & 0xFC) == 0xD8) {                                \
729       fromLim -= 2;                                                            \
730       res = XML_CONVERT_INPUT_INCOMPLETE;                                      \
731     }                                                                          \
732     for (; *fromP < fromLim && *toP < toLim; *fromP += 2)                      \
733       *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP);                      \
734     if ((*toP == toLim) && (*fromP < fromLim))                                 \
735       return XML_CONVERT_OUTPUT_EXHAUSTED;                                     \
736     else                                                                       \
737       return res;                                                              \
738   }
739 
740 #define GET_LO(ptr) ((unsigned char)(ptr)[0])
741 #define GET_HI(ptr) ((unsigned char)(ptr)[1])
742 
743 DEFINE_UTF16_TO_UTF8(little2_)
744 DEFINE_UTF16_TO_UTF16(little2_)
745 
746 #undef GET_LO
747 #undef GET_HI
748 
749 #define GET_LO(ptr) ((unsigned char)(ptr)[1])
750 #define GET_HI(ptr) ((unsigned char)(ptr)[0])
751 
752 DEFINE_UTF16_TO_UTF8(big2_)
753 DEFINE_UTF16_TO_UTF16(big2_)
754 
755 #undef GET_LO
756 #undef GET_HI
757 
758 #define LITTLE2_BYTE_TYPE(enc, p)                                              \
759   ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
760 #define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
761 #define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
762 #define LITTLE2_IS_NAME_CHAR_MINBPC(p)                                         \
763   UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
764 #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)                                       \
765   UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
766 /* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
767    for a high surrogate, so the pair is invalid unless the second unit is a low
768    surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
769 #define LITTLE2_IS_INVALID_CHAR(p, n)                                          \
770   ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC)
771 
772 #ifdef XML_MIN_SIZE
773 
774 static int
775 little2_byteType(const ENCODING *enc, const char *p) {
776   return LITTLE2_BYTE_TYPE(enc, p);
777 }
778 
779 static int
780 little2_byteToAscii(const ENCODING *enc, const char *p) {
781   UNUSED_P(enc);
782   return LITTLE2_BYTE_TO_ASCII(p);
783 }
784 
785 static int
786 little2_charMatches(const ENCODING *enc, const char *p, int c) {
787   UNUSED_P(enc);
788   return LITTLE2_CHAR_MATCHES(p, c);
789 }
790 
791 static int
792 little2_isNameMin(const ENCODING *enc, const char *p) {
793   UNUSED_P(enc);
794   return LITTLE2_IS_NAME_CHAR_MINBPC(p);
795 }
796 
797 static int
798 little2_isNmstrtMin(const ENCODING *enc, const char *p) {
799   UNUSED_P(enc);
800   return LITTLE2_IS_NMSTRT_CHAR_MINBPC(p);
801 }
802 
803 static int
804 little2_isInvalid4(const ENCODING *enc, const char *p) {
805   UNUSED_P(enc);
806   return LITTLE2_IS_INVALID_CHAR(p, 4);
807 }
808 
809 #  undef VTABLE
810 #  define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
811 
812 #else /* not XML_MIN_SIZE */
813 
814 #  undef PREFIX
815 #  define PREFIX(ident) little2_##ident
816 #  define MINBPC(enc) 2
817 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
818 #  define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
819 #  define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
820 #  define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
821 #  define IS_NAME_CHAR(enc, p, n) 0
822 #  define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
823 #  define IS_NMSTRT_CHAR(enc, p, n) (0)
824 #  define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
825 #  define IS_INVALID_CHAR(enc, p, n) LITTLE2_IS_INVALID_CHAR(p, n)
826 
827 #  define XML_TOK_IMPL_C
828 #  include "xmltok_impl.c"
829 #  undef XML_TOK_IMPL_C
830 
831 #  undef MINBPC
832 #  undef BYTE_TYPE
833 #  undef BYTE_TO_ASCII
834 #  undef CHAR_MATCHES
835 #  undef IS_NAME_CHAR
836 #  undef IS_NAME_CHAR_MINBPC
837 #  undef IS_NMSTRT_CHAR
838 #  undef IS_NMSTRT_CHAR_MINBPC
839 #  undef IS_INVALID_CHAR
840 
841 #endif /* not XML_MIN_SIZE */
842 
843 #ifdef XML_NS
844 
845 static const struct normal_encoding little2_encoding_ns
846     = {{VTABLE, 2, 0,
847 #  if BYTEORDER == 1234
848         1
849 #  else
850         0
851 #  endif
852        },
853        {
854 #  include "asciitab.h"
855 #  include "latin1tab.h"
856        },
857        STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
858 
859 #endif
860 
861 static const struct normal_encoding little2_encoding
862     = {{VTABLE, 2, 0,
863 #if BYTEORDER == 1234
864         1
865 #else
866         0
867 #endif
868        },
869        {
870 #define BT_COLON BT_NMSTRT
871 #include "asciitab.h"
872 #undef BT_COLON
873 #include "latin1tab.h"
874        },
875        STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
876 
877 #if BYTEORDER != 4321
878 
879 #  ifdef XML_NS
880 
881 static const struct normal_encoding internal_little2_encoding_ns
882     = {{VTABLE, 2, 0, 1},
883        {
884 #    include "iasciitab.h"
885 #    include "latin1tab.h"
886        },
887        STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
888 
889 #  endif
890 
891 static const struct normal_encoding internal_little2_encoding
892     = {{VTABLE, 2, 0, 1},
893        {
894 #  define BT_COLON BT_NMSTRT
895 #  include "iasciitab.h"
896 #  undef BT_COLON
897 #  include "latin1tab.h"
898        },
899        STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
900 
901 #endif
902 
903 #define BIG2_BYTE_TYPE(enc, p)                                                 \
904   ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
905 #define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
906 #define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
907 #define BIG2_IS_NAME_CHAR_MINBPC(p)                                            \
908   UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
909 #define BIG2_IS_NMSTRT_CHAR_MINBPC(p)                                          \
910   UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
911 /* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
912    for a high surrogate, so the pair is invalid unless the second unit is a low
913    surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
914 #define BIG2_IS_INVALID_CHAR(p, n)                                             \
915   ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC)
916 
917 #ifdef XML_MIN_SIZE
918 
919 static int
920 big2_byteType(const ENCODING *enc, const char *p) {
921   return BIG2_BYTE_TYPE(enc, p);
922 }
923 
924 static int
925 big2_byteToAscii(const ENCODING *enc, const char *p) {
926   UNUSED_P(enc);
927   return BIG2_BYTE_TO_ASCII(p);
928 }
929 
930 static int
931 big2_charMatches(const ENCODING *enc, const char *p, int c) {
932   UNUSED_P(enc);
933   return BIG2_CHAR_MATCHES(p, c);
934 }
935 
936 static int
937 big2_isNameMin(const ENCODING *enc, const char *p) {
938   UNUSED_P(enc);
939   return BIG2_IS_NAME_CHAR_MINBPC(p);
940 }
941 
942 static int
943 big2_isNmstrtMin(const ENCODING *enc, const char *p) {
944   UNUSED_P(enc);
945   return BIG2_IS_NMSTRT_CHAR_MINBPC(p);
946 }
947 
948 static int
949 big2_isInvalid4(const ENCODING *enc, const char *p) {
950   UNUSED_P(enc);
951   return BIG2_IS_INVALID_CHAR(p, 4);
952 }
953 
954 #  undef VTABLE
955 #  define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
956 
957 #else /* not XML_MIN_SIZE */
958 
959 #  undef PREFIX
960 #  define PREFIX(ident) big2_##ident
961 #  define MINBPC(enc) 2
962 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
963 #  define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
964 #  define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
965 #  define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
966 #  define IS_NAME_CHAR(enc, p, n) 0
967 #  define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
968 #  define IS_NMSTRT_CHAR(enc, p, n) (0)
969 #  define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
970 #  define IS_INVALID_CHAR(enc, p, n) BIG2_IS_INVALID_CHAR(p, n)
971 
972 #  define XML_TOK_IMPL_C
973 #  include "xmltok_impl.c"
974 #  undef XML_TOK_IMPL_C
975 
976 #  undef MINBPC
977 #  undef BYTE_TYPE
978 #  undef BYTE_TO_ASCII
979 #  undef CHAR_MATCHES
980 #  undef IS_NAME_CHAR
981 #  undef IS_NAME_CHAR_MINBPC
982 #  undef IS_NMSTRT_CHAR
983 #  undef IS_NMSTRT_CHAR_MINBPC
984 #  undef IS_INVALID_CHAR
985 
986 #endif /* not XML_MIN_SIZE */
987 
988 #ifdef XML_NS
989 
990 static const struct normal_encoding big2_encoding_ns
991     = {{VTABLE, 2, 0,
992 #  if BYTEORDER == 4321
993         1
994 #  else
995         0
996 #  endif
997        },
998        {
999 #  include "asciitab.h"
1000 #  include "latin1tab.h"
1001        },
1002        STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
1003 
1004 #endif
1005 
1006 static const struct normal_encoding big2_encoding
1007     = {{VTABLE, 2, 0,
1008 #if BYTEORDER == 4321
1009         1
1010 #else
1011         0
1012 #endif
1013        },
1014        {
1015 #define BT_COLON BT_NMSTRT
1016 #include "asciitab.h"
1017 #undef BT_COLON
1018 #include "latin1tab.h"
1019        },
1020        STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
1021 
1022 #if BYTEORDER != 1234
1023 
1024 #  ifdef XML_NS
1025 
1026 static const struct normal_encoding internal_big2_encoding_ns
1027     = {{VTABLE, 2, 0, 1},
1028        {
1029 #    include "iasciitab.h"
1030 #    include "latin1tab.h"
1031        },
1032        STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
1033 
1034 #  endif
1035 
1036 static const struct normal_encoding internal_big2_encoding
1037     = {{VTABLE, 2, 0, 1},
1038        {
1039 #  define BT_COLON BT_NMSTRT
1040 #  include "iasciitab.h"
1041 #  undef BT_COLON
1042 #  include "latin1tab.h"
1043        },
1044        STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
1045 
1046 #endif
1047 
1048 #undef PREFIX
1049 
1050 static int
1051 streqci(const char *s1, const char *s2) {
1052   for (;;) {
1053     char c1 = *s1++;
1054     char c2 = *s2++;
1055     if (ASCII_a <= c1 && c1 <= ASCII_z)
1056       c1 += ASCII_A - ASCII_a;
1057     if (ASCII_a <= c2 && c2 <= ASCII_z)
1058       /* The following line will never get executed.  streqci() is
1059        * only called from two places, both of which guarantee to put
1060        * upper-case strings into s2.
1061        */
1062       c2 += ASCII_A - ASCII_a; /* LCOV_EXCL_LINE */
1063     if (c1 != c2)
1064       return 0;
1065     if (! c1)
1066       break;
1067   }
1068   return 1;
1069 }
1070 
1071 static void
1072 initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
1073                    POSITION *pos) {
1074   UNUSED_P(enc);
1075   normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
1076 }
1077 
1078 static int
1079 toAscii(const ENCODING *enc, const char *ptr, const char *end) {
1080   char buf[1];
1081   char *p = buf;
1082   XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
1083   if (p == buf)
1084     return -1;
1085   else
1086     return buf[0];
1087 }
1088 
1089 static int
1090 isSpace(int c) {
1091   switch (c) {
1092   case 0x20:
1093   case 0xD:
1094   case 0xA:
1095   case 0x9:
1096     return 1;
1097   }
1098   return 0;
1099 }
1100 
1101 /* Return 1 if there's just optional white space or there's an S
1102    followed by name=val.
1103 */
1104 static int
1105 parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end,
1106                      const char **namePtr, const char **nameEndPtr,
1107                      const char **valPtr, const char **nextTokPtr) {
1108   int c;
1109   char open;
1110   if (ptr == end) {
1111     *namePtr = NULL;
1112     return 1;
1113   }
1114   if (! isSpace(toAscii(enc, ptr, end))) {
1115     *nextTokPtr = ptr;
1116     return 0;
1117   }
1118   do {
1119     ptr += enc->minBytesPerChar;
1120   } while (isSpace(toAscii(enc, ptr, end)));
1121   if (ptr == end) {
1122     *namePtr = NULL;
1123     return 1;
1124   }
1125   *namePtr = ptr;
1126   for (;;) {
1127     c = toAscii(enc, ptr, end);
1128     if (c == -1) {
1129       *nextTokPtr = ptr;
1130       return 0;
1131     }
1132     if (c == ASCII_EQUALS) {
1133       *nameEndPtr = ptr;
1134       break;
1135     }
1136     if (isSpace(c)) {
1137       *nameEndPtr = ptr;
1138       do {
1139         ptr += enc->minBytesPerChar;
1140       } while (isSpace(c = toAscii(enc, ptr, end)));
1141       if (c != ASCII_EQUALS) {
1142         *nextTokPtr = ptr;
1143         return 0;
1144       }
1145       break;
1146     }
1147     ptr += enc->minBytesPerChar;
1148   }
1149   if (ptr == *namePtr) {
1150     *nextTokPtr = ptr;
1151     return 0;
1152   }
1153   ptr += enc->minBytesPerChar;
1154   c = toAscii(enc, ptr, end);
1155   while (isSpace(c)) {
1156     ptr += enc->minBytesPerChar;
1157     c = toAscii(enc, ptr, end);
1158   }
1159   if (c != ASCII_QUOT && c != ASCII_APOS) {
1160     *nextTokPtr = ptr;
1161     return 0;
1162   }
1163   open = (char)c;
1164   ptr += enc->minBytesPerChar;
1165   *valPtr = ptr;
1166   for (;; ptr += enc->minBytesPerChar) {
1167     c = toAscii(enc, ptr, end);
1168     if (c == open)
1169       break;
1170     if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1171         && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1172         && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1173       *nextTokPtr = ptr;
1174       return 0;
1175     }
1176   }
1177   *nextTokPtr = ptr + enc->minBytesPerChar;
1178   return 1;
1179 }
1180 
1181 static const char KW_version[]
1182     = {ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'};
1183 
1184 static const char KW_encoding[] = {ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d,
1185                                    ASCII_i, ASCII_n, ASCII_g, '\0'};
1186 
1187 static const char KW_standalone[]
1188     = {ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a,
1189        ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'};
1190 
1191 static const char KW_yes[] = {ASCII_y, ASCII_e, ASCII_s, '\0'};
1192 
1193 static const char KW_no[] = {ASCII_n, ASCII_o, '\0'};
1194 
1195 static const char KW_1_dot[] = {ASCII_1, ASCII_PERIOD, '\0'};
1196 
1197 /* Checks a version pseudo-attribute value against the VersionNum production.
1198    XML 1.0 Fourth Edition only allows the literal "1.0", but the Fifth
1199    Edition relaxed this to "1." followed by one or more digits, since Expat
1200    only implements 1.0 itself but plans to track the Fifth Edition's laxer
1201    grammar here so that "1.1" and similar aren't rejected only to have that
1202    rejection reverted later. Returns true for a value matching "1.[0-9]+".
1203    val/valEnd bound the value itself; valEnd is the upper bound used when
1204    decoding the individual characters between them. */
1205 static bool
1206 checkXmlDeclVersionNum(const ENCODING *enc, const char *val,
1207                        const char *valEnd) {
1208   if (valEnd - val < 2 * enc->minBytesPerChar
1209       || ! XmlNameMatchesAscii(enc, val, val + 2 * enc->minBytesPerChar,
1210                                KW_1_dot))
1211     return false;
1212   val += 2 * enc->minBytesPerChar;
1213   if (val == valEnd)
1214     return false;
1215   for (; val != valEnd; val += enc->minBytesPerChar) {
1216     int c = toAscii(enc, val, valEnd);
1217     if (c < ASCII_0 || c > ASCII_9)
1218       return false;
1219   }
1220   return true;
1221 }
1222 
1223 static int
1224 doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
1225                                                  const char *),
1226                int isGeneralTextEntity, const ENCODING *enc, const char *ptr,
1227                const char *end, const char **badPtr, const char **versionPtr,
1228                const char **versionEndPtr, const char **encodingName,
1229                const ENCODING **encoding, int *standalone) {
1230   const char *val = NULL;
1231   const char *name = NULL;
1232   const char *nameEnd = NULL;
1233   ptr += 5 * enc->minBytesPerChar;
1234   end -= 2 * enc->minBytesPerChar;
1235   if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1236       || ! name) {
1237     *badPtr = ptr;
1238     return 0;
1239   }
1240   if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
1241     if (! isGeneralTextEntity) {
1242       *badPtr = name;
1243       return 0;
1244     }
1245   } else {
1246     if (versionPtr)
1247       *versionPtr = val;
1248     if (versionEndPtr)
1249       *versionEndPtr = ptr;
1250     /* The version number must not be empty; VersionNum requires at least
1251        one character.  The encoding and standalone pseudo-attributes below
1252        already reject an empty value, so keep version consistent. */
1253     if (val == ptr - enc->minBytesPerChar) {
1254       *badPtr = val;
1255       return 0;
1256     }
1257     /* Expat implements XML 1.0 only, so any version outside the "1.0"/"1.x"
1258        family is rejected. Following the Fifth Edition's VersionNum
1259        production (rather than the Fourth Edition's exact "1.0") avoids
1260        rejecting "1.1" now only to have to revert that once Expat tracks
1261        the newer edition. */
1262     if (! checkXmlDeclVersionNum(enc, val, ptr - enc->minBytesPerChar)) {
1263       *badPtr = val;
1264       return 0;
1265     }
1266     if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1267       *badPtr = ptr;
1268       return 0;
1269     }
1270     if (! name) {
1271       if (isGeneralTextEntity) {
1272         /* a TextDecl must have an EncodingDecl */
1273         *badPtr = ptr;
1274         return 0;
1275       }
1276       return 1;
1277     }
1278   }
1279   if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
1280     int c = toAscii(enc, val, end);
1281     if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)) {
1282       *badPtr = val;
1283       return 0;
1284     }
1285     if (encodingName)
1286       *encodingName = val;
1287     if (encoding)
1288       *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
1289     if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1290       *badPtr = ptr;
1291       return 0;
1292     }
1293     if (! name)
1294       return 1;
1295   }
1296   if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
1297       || isGeneralTextEntity) {
1298     *badPtr = name;
1299     return 0;
1300   }
1301   if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
1302     if (standalone)
1303       *standalone = 1;
1304   } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
1305     if (standalone)
1306       *standalone = 0;
1307   } else {
1308     *badPtr = val;
1309     return 0;
1310   }
1311   while (isSpace(toAscii(enc, ptr, end)))
1312     ptr += enc->minBytesPerChar;
1313   if (ptr != end) {
1314     *badPtr = ptr;
1315     return 0;
1316   }
1317   return 1;
1318 }
1319 
1320 static int
1321 checkCharRefNumber(int result) {
1322   switch (result >> 8) {
1323   case 0xD8:
1324   case 0xD9:
1325   case 0xDA:
1326   case 0xDB:
1327   case 0xDC:
1328   case 0xDD:
1329   case 0xDE:
1330   case 0xDF:
1331     return -1;
1332   case 0:
1333     if (latin1_encoding.type[result] == BT_NONXML)
1334       return -1;
1335     break;
1336   case 0xFF:
1337     if (result == 0xFFFE || result == 0xFFFF)
1338       return -1;
1339     break;
1340   }
1341   return result;
1342 }
1343 
1344 int
1345 XmlUtf8Encode(int c, char *buf) {
1346   enum {
1347     /* minN is minimum legal resulting value for N byte sequence */
1348     min2 = 0x80,
1349     min3 = 0x800,
1350     min4 = 0x10000
1351   };
1352 
1353   if (c < 0)
1354     return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1355   if (c < min2) {
1356     buf[0] = (char)(c | UTF8_cval1);
1357     return 1;
1358   }
1359   if (c < min3) {
1360     buf[0] = (char)((c >> 6) | UTF8_cval2);
1361     buf[1] = (char)((c & 0x3f) | 0x80);
1362     return 2;
1363   }
1364   if (c < min4) {
1365     buf[0] = (char)((c >> 12) | UTF8_cval3);
1366     buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
1367     buf[2] = (char)((c & 0x3f) | 0x80);
1368     return 3;
1369   }
1370   if (c < 0x110000) {
1371     buf[0] = (char)((c >> 18) | UTF8_cval4);
1372     buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
1373     buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
1374     buf[3] = (char)((c & 0x3f) | 0x80);
1375     return 4;
1376   }
1377   return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
1378 }
1379 
1380 int
1381 XmlUtf16Encode(int charNum, unsigned short *buf) {
1382   if (charNum < 0)
1383     return 0;
1384   if (charNum < 0x10000) {
1385     buf[0] = (unsigned short)charNum;
1386     return 1;
1387   }
1388   if (charNum < 0x110000) {
1389     charNum -= 0x10000;
1390     buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
1391     buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
1392     return 2;
1393   }
1394   return 0;
1395 }
1396 
1397 struct unknown_encoding {
1398   struct normal_encoding normal;
1399   CONVERTER convert;
1400   void *userData;
1401   unsigned short utf16[256];
1402   char utf8[256][4];
1403 };
1404 
1405 #define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *)(enc))
1406 
1407 int
1408 XmlSizeOfUnknownEncoding(void) {
1409   return sizeof(struct unknown_encoding);
1410 }
1411 
1412 static int
1413 unknown_isName(const ENCODING *enc, const char *p) {
1414   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1415   int c = uenc->convert(uenc->userData, p);
1416   if (c & ~0xFFFF)
1417     return 0;
1418   return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
1419 }
1420 
1421 static int
1422 unknown_isNmstrt(const ENCODING *enc, const char *p) {
1423   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1424   int c = uenc->convert(uenc->userData, p);
1425   if (c & ~0xFFFF)
1426     return 0;
1427   return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
1428 }
1429 
1430 static int
1431 unknown_isInvalid(const ENCODING *enc, const char *p) {
1432   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1433   int c = uenc->convert(uenc->userData, p);
1434   return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
1435 }
1436 
1437 static enum XML_Convert_Result
1438 unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
1439                char **toP, const char *toLim) {
1440   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1441   char buf[XML_UTF8_ENCODE_MAX];
1442   for (;;) {
1443     const char *utf8;
1444     int n;
1445     if (*fromP == fromLim)
1446       return XML_CONVERT_COMPLETED;
1447     utf8 = uenc->utf8[(unsigned char)**fromP];
1448     n = *utf8++;
1449     if (n == 0) {
1450       int c = uenc->convert(uenc->userData, *fromP);
1451       n = XmlUtf8Encode(c, buf);
1452       if (n > toLim - *toP)
1453         return XML_CONVERT_OUTPUT_EXHAUSTED;
1454       utf8 = buf;
1455       *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1456                  - (BT_LEAD2 - 2));
1457     } else {
1458       if (n > toLim - *toP)
1459         return XML_CONVERT_OUTPUT_EXHAUSTED;
1460       (*fromP)++;
1461     }
1462     memcpy(*toP, utf8, n);
1463     *toP += n;
1464   }
1465 }
1466 
1467 static enum XML_Convert_Result
1468 unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
1469                 unsigned short **toP, const unsigned short *toLim) {
1470   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1471   while (*fromP < fromLim && *toP < toLim) {
1472     unsigned short c = uenc->utf16[(unsigned char)**fromP];
1473     if (c == 0) {
1474       c = (unsigned short)uenc->convert(uenc->userData, *fromP);
1475       *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1476                  - (BT_LEAD2 - 2));
1477     } else
1478       (*fromP)++;
1479     *(*toP)++ = c;
1480   }
1481 
1482   if ((*toP == toLim) && (*fromP < fromLim))
1483     return XML_CONVERT_OUTPUT_EXHAUSTED;
1484   else
1485     return XML_CONVERT_COMPLETED;
1486 }
1487 
1488 ENCODING *
1489 XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert,
1490                        void *userData) {
1491   int i;
1492   struct unknown_encoding *e = (struct unknown_encoding *)mem;
1493   memcpy(mem, &latin1_encoding, sizeof(struct normal_encoding));
1494   for (i = 0; i < 128; i++)
1495     if (latin1_encoding.type[i] != BT_OTHER
1496         && latin1_encoding.type[i] != BT_NONXML && table[i] != i)
1497       return 0;
1498   for (i = 0; i < 256; i++) {
1499     int c = table[i];
1500     if (c == -1) {
1501       e->normal.type[i] = BT_MALFORM;
1502       /* This shouldn't really get used. */
1503       e->utf16[i] = 0xFFFF;
1504       e->utf8[i][0] = 1;
1505       e->utf8[i][1] = 0;
1506     } else if (c < 0) {
1507       if (c < -4)
1508         return 0;
1509       /* Multi-byte sequences need a converter function */
1510       if (! convert)
1511         return 0;
1512       e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
1513       e->utf8[i][0] = 0;
1514       e->utf16[i] = 0;
1515     } else if (c < 0x80) {
1516       if (latin1_encoding.type[c] != BT_OTHER
1517           && latin1_encoding.type[c] != BT_NONXML && c != i)
1518         return 0;
1519       e->normal.type[i] = latin1_encoding.type[c];
1520       e->utf8[i][0] = 1;
1521       e->utf8[i][1] = (char)c;
1522       e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
1523     } else if (checkCharRefNumber(c) < 0) {
1524       e->normal.type[i] = BT_NONXML;
1525       /* This shouldn't really get used. */
1526       e->utf16[i] = 0xFFFF;
1527       e->utf8[i][0] = 1;
1528       e->utf8[i][1] = 0;
1529     } else {
1530       if (c > 0xFFFF)
1531         return 0;
1532       if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
1533         e->normal.type[i] = BT_NMSTRT;
1534       else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
1535         e->normal.type[i] = BT_NAME;
1536       else
1537         e->normal.type[i] = BT_OTHER;
1538       e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
1539       e->utf16[i] = (unsigned short)c;
1540     }
1541   }
1542   e->userData = userData;
1543   e->convert = convert;
1544   if (convert) {
1545     e->normal.isName2 = unknown_isName;
1546     e->normal.isName3 = unknown_isName;
1547     e->normal.isName4 = unknown_isName;
1548     e->normal.isNmstrt2 = unknown_isNmstrt;
1549     e->normal.isNmstrt3 = unknown_isNmstrt;
1550     e->normal.isNmstrt4 = unknown_isNmstrt;
1551     e->normal.isInvalid2 = unknown_isInvalid;
1552     e->normal.isInvalid3 = unknown_isInvalid;
1553     e->normal.isInvalid4 = unknown_isInvalid;
1554   }
1555   e->normal.enc.utf8Convert = unknown_toUtf8;
1556   e->normal.enc.utf16Convert = unknown_toUtf16;
1557   return &(e->normal.enc);
1558 }
1559 
1560 /* If this enumeration is changed, getEncodingIndex and encodings
1561 must also be changed. */
1562 enum {
1563   UNKNOWN_ENC = -1,
1564   ISO_8859_1_ENC = 0,
1565   US_ASCII_ENC,
1566   UTF_8_ENC,
1567   UTF_16_ENC,
1568   UTF_16BE_ENC,
1569   UTF_16LE_ENC,
1570   /* must match encodingNames up to here */
1571   NO_ENC
1572 };
1573 
1574 static const char KW_ISO_8859_1[]
1575     = {ASCII_I, ASCII_S, ASCII_O,     ASCII_MINUS, ASCII_8, ASCII_8,
1576        ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1,     '\0'};
1577 static const char KW_US_ASCII[]
1578     = {ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S,
1579        ASCII_C, ASCII_I, ASCII_I,     '\0'};
1580 static const char KW_UTF_8[]
1581     = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'};
1582 static const char KW_UTF_16[]
1583     = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'};
1584 static const char KW_UTF_16BE[]
1585     = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
1586        ASCII_6, ASCII_B, ASCII_E, '\0'};
1587 static const char KW_UTF_16LE[]
1588     = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
1589        ASCII_6, ASCII_L, ASCII_E, '\0'};
1590 
1591 static int
1592 getEncodingIndex(const char *name) {
1593   static const char *const encodingNames[] = {
1594       KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1595   };
1596   int i;
1597   if (name == NULL)
1598     return NO_ENC;
1599   for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++)
1600     if (streqci(name, encodingNames[i]))
1601       return i;
1602   return UNKNOWN_ENC;
1603 }
1604 
1605 /* For binary compatibility, we store the index of the encoding
1606    specified at initialization in the isUtf16 member.
1607 */
1608 
1609 #define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1610 #define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
1611 
1612 /* This is what detects the encoding.  encodingTable maps from
1613    encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of
1614    the external (protocol) specified encoding; state is
1615    XML_CONTENT_STATE if we're parsing an external text entity, and
1616    XML_PROLOG_STATE otherwise.
1617 */
1618 
1619 static int
1620 initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc,
1621          int state, const char *ptr, const char *end, const char **nextTokPtr) {
1622   const ENCODING **encPtr;
1623 
1624   if (ptr >= end)
1625     return XML_TOK_NONE;
1626   encPtr = enc->encPtr;
1627   if (ptr + 1 == end) {
1628     /* only a single byte available for auto-detection */
1629 #ifndef XML_DTD /* FIXME */
1630     /* a well-formed document entity must have more than one byte */
1631     if (state != XML_CONTENT_STATE)
1632       return XML_TOK_PARTIAL;
1633 #endif
1634     /* so we're parsing an external text entity... */
1635     /* if UTF-16 was externally specified, then we need at least 2 bytes */
1636     switch (INIT_ENC_INDEX(enc)) {
1637     case UTF_16_ENC:
1638     case UTF_16LE_ENC:
1639     case UTF_16BE_ENC:
1640       return XML_TOK_PARTIAL;
1641     }
1642     switch ((unsigned char)*ptr) {
1643     case 0xFE:
1644     case 0xFF:
1645     case 0xEF: /* possibly first byte of UTF-8 BOM */
1646       if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1647         break;
1648       EXPAT_FALLTHROUGH;
1649     case 0x00:
1650     case 0x3C:
1651       return XML_TOK_PARTIAL;
1652     }
1653   } else {
1654     switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1655     case 0xFEFF:
1656       if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1657         break;
1658       *nextTokPtr = ptr + 2;
1659       *encPtr = encodingTable[UTF_16BE_ENC];
1660       return XML_TOK_BOM;
1661     /* 00 3C is handled in the default case */
1662     case 0x3C00:
1663       if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1664            || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1665           && state == XML_CONTENT_STATE)
1666         break;
1667       *encPtr = encodingTable[UTF_16LE_ENC];
1668       return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1669     case 0xFFFE:
1670       if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1671         break;
1672       *nextTokPtr = ptr + 2;
1673       *encPtr = encodingTable[UTF_16LE_ENC];
1674       return XML_TOK_BOM;
1675     case 0xEFBB:
1676       /* Maybe a UTF-8 BOM (EF BB BF) */
1677       /* If there's an explicitly specified (external) encoding
1678          of ISO-8859-1 or some flavour of UTF-16
1679          and this is an external text entity,
1680          don't look for the BOM,
1681          because it might be a legal data.
1682       */
1683       if (state == XML_CONTENT_STATE) {
1684         int e = INIT_ENC_INDEX(enc);
1685         if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC
1686             || e == UTF_16_ENC)
1687           break;
1688       }
1689       if (ptr + 2 == end)
1690         return XML_TOK_PARTIAL;
1691       if ((unsigned char)ptr[2] == 0xBF) {
1692         *nextTokPtr = ptr + 3;
1693         *encPtr = encodingTable[UTF_8_ENC];
1694         return XML_TOK_BOM;
1695       }
1696       break;
1697     default:
1698       if (ptr[0] == '\0') {
1699         /* 0 isn't a legal data character. Furthermore a document
1700            entity can only start with ASCII characters.  So the only
1701            way this can fail to be big-endian UTF-16 if it it's an
1702            external parsed general entity that's labelled as
1703            UTF-16LE.
1704         */
1705         if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1706           break;
1707         *encPtr = encodingTable[UTF_16BE_ENC];
1708         return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1709       } else if (ptr[1] == '\0') {
1710         /* We could recover here in the case:
1711             - parsing an external entity
1712             - second byte is 0
1713             - no externally specified encoding
1714             - no encoding declaration
1715            by assuming UTF-16LE.  But we don't, because this would mean when
1716            presented just with a single byte, we couldn't reliably determine
1717            whether we needed further bytes.
1718         */
1719         if (state == XML_CONTENT_STATE)
1720           break;
1721         *encPtr = encodingTable[UTF_16LE_ENC];
1722         return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1723       }
1724       break;
1725     }
1726   }
1727   *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1728   return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1729 }
1730 
1731 #define NS(x) x
1732 #define ns(x) x
1733 #define XML_TOK_NS_C
1734 #include "xmltok_ns.c"
1735 #undef XML_TOK_NS_C
1736 #undef NS
1737 #undef ns
1738 
1739 #ifdef XML_NS
1740 
1741 #  define NS(x) x##NS
1742 #  define ns(x) x##_ns
1743 
1744 #  define XML_TOK_NS_C
1745 #  include "xmltok_ns.c"
1746 #  undef XML_TOK_NS_C
1747 
1748 #  undef NS
1749 #  undef ns
1750 
1751 ENCODING *
1752 XmlInitUnknownEncodingNS(void *mem, const int *table, CONVERTER convert,
1753                          void *userData) {
1754   ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
1755   if (enc)
1756     ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
1757   return enc;
1758 }
1759 
1760 #endif /* XML_NS */
1761