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