Line data Source code
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 23 : PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
91 : const char *end, const char **nextTokPtr)
92 : {
93 23 : if (ptr != end) {
94 23 : if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
95 0 : *nextTokPtr = ptr;
96 0 : return XML_TOK_INVALID;
97 : }
98 23 : ptr += MINBPC(enc);
99 4740 : while (ptr != end) {
100 4717 : switch (BYTE_TYPE(enc, ptr)) {
101 0 : INVALID_CASES(ptr, nextTokPtr)
102 : case BT_MINUS:
103 69 : if ((ptr += MINBPC(enc)) == end)
104 0 : return XML_TOK_PARTIAL;
105 69 : if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
106 23 : if ((ptr += MINBPC(enc)) == end)
107 0 : return XML_TOK_PARTIAL;
108 23 : if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
109 0 : *nextTokPtr = ptr;
110 0 : return XML_TOK_INVALID;
111 : }
112 23 : *nextTokPtr = ptr + MINBPC(enc);
113 23 : return XML_TOK_COMMENT;
114 : }
115 46 : break;
116 : default:
117 4648 : ptr += MINBPC(enc);
118 4648 : break;
119 : }
120 : }
121 : }
122 0 : return XML_TOK_PARTIAL;
123 : }
124 :
125 : /* ptr points to character following "<!" */
126 :
127 : static int PTRCALL
128 21 : PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
129 : const char *end, const char **nextTokPtr)
130 : {
131 21 : if (ptr == end)
132 0 : return XML_TOK_PARTIAL;
133 21 : switch (BYTE_TYPE(enc, ptr)) {
134 : case BT_MINUS:
135 21 : 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 0 : ptr += MINBPC(enc);
142 0 : break;
143 : default:
144 0 : *nextTokPtr = ptr;
145 0 : return XML_TOK_INVALID;
146 : }
147 0 : while (ptr != end) {
148 0 : 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 0 : *nextTokPtr = ptr;
161 0 : return XML_TOK_DECL_OPEN;
162 : case BT_NMSTRT:
163 : case BT_HEX:
164 0 : ptr += MINBPC(enc);
165 0 : 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 4 : PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr,
176 : const char *end, int *tokPtr)
177 : {
178 4 : int upper = 0;
179 4 : *tokPtr = XML_TOK_PI;
180 4 : if (end - ptr != MINBPC(enc)*3)
181 0 : return 1;
182 4 : switch (BYTE_TO_ASCII(enc, ptr)) {
183 : case ASCII_x:
184 4 : break;
185 : case ASCII_X:
186 0 : upper = 1;
187 0 : break;
188 : default:
189 0 : return 1;
190 : }
191 4 : ptr += MINBPC(enc);
192 4 : switch (BYTE_TO_ASCII(enc, ptr)) {
193 : case ASCII_m:
194 4 : break;
195 : case ASCII_M:
196 0 : upper = 1;
197 0 : break;
198 : default:
199 0 : return 1;
200 : }
201 4 : ptr += MINBPC(enc);
202 4 : switch (BYTE_TO_ASCII(enc, ptr)) {
203 : case ASCII_l:
204 4 : break;
205 : case ASCII_L:
206 0 : upper = 1;
207 0 : break;
208 : default:
209 0 : return 1;
210 : }
211 4 : if (upper)
212 0 : return 0;
213 4 : *tokPtr = XML_TOK_XML_DECL;
214 4 : return 1;
215 : }
216 :
217 : /* ptr points to character following "<?" */
218 :
219 : static int PTRCALL
220 4 : PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
221 : const char *end, const char **nextTokPtr)
222 : {
223 : int tok;
224 4 : const char *target = ptr;
225 4 : if (ptr == end)
226 0 : return XML_TOK_PARTIAL;
227 4 : 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 16 : while (ptr != end) {
234 12 : 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 4 : if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
238 0 : *nextTokPtr = ptr;
239 0 : return XML_TOK_INVALID;
240 : }
241 4 : ptr += MINBPC(enc);
242 111 : while (ptr != end) {
243 107 : switch (BYTE_TYPE(enc, ptr)) {
244 0 : INVALID_CASES(ptr, nextTokPtr)
245 : case BT_QUEST:
246 4 : ptr += MINBPC(enc);
247 4 : if (ptr == end)
248 0 : return XML_TOK_PARTIAL;
249 4 : if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
250 4 : *nextTokPtr = ptr + MINBPC(enc);
251 4 : return tok;
252 : }
253 0 : break;
254 : default:
255 103 : ptr += MINBPC(enc);
256 103 : break;
257 : }
258 : }
259 0 : return XML_TOK_PARTIAL;
260 : case BT_QUEST:
261 0 : if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
262 0 : *nextTokPtr = ptr;
263 0 : return XML_TOK_INVALID;
264 : }
265 0 : ptr += MINBPC(enc);
266 0 : if (ptr == end)
267 0 : return XML_TOK_PARTIAL;
268 0 : if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
269 0 : *nextTokPtr = ptr + MINBPC(enc);
270 0 : 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 0 : 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 0 : if (end - ptr < 6 * MINBPC(enc))
290 0 : return XML_TOK_PARTIAL;
291 0 : for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
292 0 : if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
293 0 : *nextTokPtr = ptr;
294 0 : return XML_TOK_INVALID;
295 : }
296 : }
297 0 : *nextTokPtr = ptr;
298 0 : return XML_TOK_CDATA_SECT_OPEN;
299 : }
300 :
301 : static int PTRCALL
302 0 : PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
303 : const char *end, const char **nextTokPtr)
304 : {
305 0 : if (ptr == end)
306 0 : return XML_TOK_NONE;
307 : if (MINBPC(enc) > 1) {
308 0 : size_t n = end - ptr;
309 0 : 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 0 : switch (BYTE_TYPE(enc, ptr)) {
317 : case BT_RSQB:
318 0 : ptr += MINBPC(enc);
319 0 : if (ptr == end)
320 0 : return XML_TOK_PARTIAL;
321 0 : if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
322 0 : break;
323 0 : ptr += MINBPC(enc);
324 0 : if (ptr == end)
325 0 : return XML_TOK_PARTIAL;
326 0 : if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
327 0 : ptr -= MINBPC(enc);
328 0 : break;
329 : }
330 0 : *nextTokPtr = ptr + MINBPC(enc);
331 0 : 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 0 : *nextTokPtr = ptr + MINBPC(enc);
342 0 : return XML_TOK_DATA_NEWLINE;
343 0 : INVALID_CASES(ptr, nextTokPtr)
344 : default:
345 0 : ptr += MINBPC(enc);
346 0 : break;
347 : }
348 0 : while (ptr != end) {
349 0 : 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 0 : *nextTokPtr = ptr;
367 0 : return XML_TOK_DATA_CHARS;
368 : default:
369 0 : ptr += MINBPC(enc);
370 0 : break;
371 : }
372 : }
373 0 : *nextTokPtr = ptr;
374 0 : return XML_TOK_DATA_CHARS;
375 : }
376 :
377 : /* ptr points to character following "</" */
378 :
379 : static int PTRCALL
380 59 : PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
381 : const char *end, const char **nextTokPtr)
382 : {
383 59 : if (ptr == end)
384 0 : return XML_TOK_PARTIAL;
385 59 : 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 314 : while (ptr != end) {
392 255 : 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 0 : 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 0 : 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 0 : 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 5 : ptr += MINBPC(enc);
413 5 : break;
414 : #endif
415 : case BT_GT:
416 59 : *nextTokPtr = ptr + MINBPC(enc);
417 59 : return XML_TOK_END_TAG;
418 : default:
419 0 : *nextTokPtr = ptr;
420 0 : return XML_TOK_INVALID;
421 : }
422 : }
423 0 : return XML_TOK_PARTIAL;
424 : }
425 :
426 : /* ptr points to character following "&#X" */
427 :
428 : static int PTRCALL
429 0 : PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
430 : const char *end, const char **nextTokPtr)
431 : {
432 0 : if (ptr != end) {
433 0 : switch (BYTE_TYPE(enc, ptr)) {
434 : case BT_DIGIT:
435 : case BT_HEX:
436 0 : break;
437 : default:
438 0 : *nextTokPtr = ptr;
439 0 : return XML_TOK_INVALID;
440 : }
441 0 : for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
442 0 : switch (BYTE_TYPE(enc, ptr)) {
443 : case BT_DIGIT:
444 : case BT_HEX:
445 0 : break;
446 : case BT_SEMI:
447 0 : *nextTokPtr = ptr + MINBPC(enc);
448 0 : return XML_TOK_CHAR_REF;
449 : default:
450 0 : *nextTokPtr = ptr;
451 0 : return XML_TOK_INVALID;
452 : }
453 : }
454 : }
455 0 : return XML_TOK_PARTIAL;
456 : }
457 :
458 : /* ptr points to character following "&#" */
459 :
460 : static int PTRCALL
461 0 : PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
462 : const char *end, const char **nextTokPtr)
463 : {
464 0 : if (ptr != end) {
465 0 : if (CHAR_MATCHES(enc, ptr, ASCII_x))
466 0 : return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
467 0 : switch (BYTE_TYPE(enc, ptr)) {
468 : case BT_DIGIT:
469 0 : break;
470 : default:
471 0 : *nextTokPtr = ptr;
472 0 : return XML_TOK_INVALID;
473 : }
474 0 : for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
475 0 : switch (BYTE_TYPE(enc, ptr)) {
476 : case BT_DIGIT:
477 0 : break;
478 : case BT_SEMI:
479 0 : *nextTokPtr = ptr + MINBPC(enc);
480 0 : 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 0 : PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
494 : const char **nextTokPtr)
495 : {
496 0 : if (ptr == end)
497 0 : return XML_TOK_PARTIAL;
498 0 : switch (BYTE_TYPE(enc, ptr)) {
499 0 : CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
500 : case BT_NUM:
501 0 : return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
502 : default:
503 0 : *nextTokPtr = ptr;
504 0 : return XML_TOK_INVALID;
505 : }
506 0 : while (ptr != end) {
507 0 : switch (BYTE_TYPE(enc, ptr)) {
508 0 : CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
509 : case BT_SEMI:
510 0 : *nextTokPtr = ptr + MINBPC(enc);
511 0 : 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 135 : PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
524 : const char **nextTokPtr)
525 : {
526 : #ifdef XML_NS
527 135 : int hadColon = 0;
528 : #endif
529 1966 : while (ptr != end) {
530 1831 : switch (BYTE_TYPE(enc, ptr)) {
531 0 : CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
532 : #ifdef XML_NS
533 : case BT_COLON:
534 35 : if (hadColon) {
535 0 : *nextTokPtr = ptr;
536 0 : return XML_TOK_INVALID;
537 : }
538 35 : hadColon = 1;
539 35 : ptr += MINBPC(enc);
540 35 : if (ptr == end)
541 0 : return XML_TOK_PARTIAL;
542 35 : 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 35 : break;
549 : #endif
550 : case BT_S: case BT_CR: case BT_LF:
551 0 : 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 0 : break;
565 : default:
566 0 : *nextTokPtr = ptr;
567 0 : return XML_TOK_INVALID;
568 : }
569 : }
570 : /* fall through */
571 : case BT_EQUALS:
572 : {
573 : int open;
574 : #ifdef XML_NS
575 357 : hadColon = 0;
576 : #endif
577 : for (;;) {
578 357 : ptr += MINBPC(enc);
579 357 : if (ptr == end)
580 0 : return XML_TOK_PARTIAL;
581 357 : open = BYTE_TYPE(enc, ptr);
582 357 : 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 0 : break;
589 : default:
590 0 : *nextTokPtr = ptr;
591 0 : return XML_TOK_INVALID;
592 : }
593 : }
594 357 : ptr += MINBPC(enc);
595 : /* in attribute value */
596 16319 : for (;;) {
597 : int t;
598 16676 : if (ptr == end)
599 0 : return XML_TOK_PARTIAL;
600 16676 : t = BYTE_TYPE(enc, ptr);
601 16676 : if (t == open)
602 357 : break;
603 16319 : switch (t) {
604 0 : INVALID_CASES(ptr, nextTokPtr)
605 : case BT_AMP:
606 : {
607 0 : int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
608 0 : if (tok <= 0) {
609 0 : if (tok == XML_TOK_INVALID)
610 0 : *nextTokPtr = ptr;
611 0 : return tok;
612 : }
613 0 : break;
614 : }
615 : case BT_LT:
616 0 : *nextTokPtr = ptr;
617 0 : return XML_TOK_INVALID;
618 : default:
619 16319 : ptr += MINBPC(enc);
620 16319 : break;
621 : }
622 : }
623 357 : ptr += MINBPC(enc);
624 357 : if (ptr == end)
625 0 : return XML_TOK_PARTIAL;
626 357 : switch (BYTE_TYPE(enc, ptr)) {
627 : case BT_S:
628 : case BT_CR:
629 : case BT_LF:
630 242 : break;
631 : case BT_SOL:
632 67 : goto sol;
633 : case BT_GT:
634 48 : goto gt;
635 : default:
636 0 : *nextTokPtr = ptr;
637 0 : return XML_TOK_INVALID;
638 : }
639 : /* ptr points to closing quote */
640 : for (;;) {
641 322 : ptr += MINBPC(enc);
642 282 : if (ptr == end)
643 0 : return XML_TOK_PARTIAL;
644 282 : 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 40 : continue;
648 : case BT_GT:
649 : gt:
650 48 : *nextTokPtr = ptr + MINBPC(enc);
651 48 : return XML_TOK_START_TAG_WITH_ATTS;
652 : case BT_SOL:
653 : sol:
654 87 : ptr += MINBPC(enc);
655 87 : if (ptr == end)
656 0 : return XML_TOK_PARTIAL;
657 87 : if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
658 0 : *nextTokPtr = ptr;
659 0 : return XML_TOK_INVALID;
660 : }
661 87 : *nextTokPtr = ptr + MINBPC(enc);
662 87 : return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
663 : default:
664 0 : *nextTokPtr = ptr;
665 0 : return XML_TOK_INVALID;
666 : }
667 222 : break;
668 : }
669 222 : break;
670 : }
671 : default:
672 0 : *nextTokPtr = ptr;
673 0 : return XML_TOK_INVALID;
674 : }
675 : }
676 0 : return XML_TOK_PARTIAL;
677 : }
678 :
679 : /* ptr points to character following "<" */
680 :
681 : static int PTRCALL
682 207 : 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 207 : if (ptr == end)
689 0 : return XML_TOK_PARTIAL;
690 207 : switch (BYTE_TYPE(enc, ptr)) {
691 0 : CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
692 : case BT_EXCL:
693 2 : if ((ptr += MINBPC(enc)) == end)
694 0 : return XML_TOK_PARTIAL;
695 2 : switch (BYTE_TYPE(enc, ptr)) {
696 : case BT_MINUS:
697 2 : return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
698 : case BT_LSQB:
699 0 : 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 0 : return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
706 : case BT_SOL:
707 59 : 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 146 : hadColon = 0;
714 : #endif
715 : /* we have a start-tag */
716 812 : while (ptr != end) {
717 666 : switch (BYTE_TYPE(enc, ptr)) {
718 0 : CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
719 : #ifdef XML_NS
720 : case BT_COLON:
721 14 : if (hadColon) {
722 0 : *nextTokPtr = ptr;
723 0 : return XML_TOK_INVALID;
724 : }
725 14 : hadColon = 1;
726 14 : ptr += MINBPC(enc);
727 14 : if (ptr == end)
728 0 : return XML_TOK_PARTIAL;
729 14 : 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 14 : break;
736 : #endif
737 : case BT_S: case BT_CR: case BT_LF:
738 : {
739 135 : ptr += MINBPC(enc);
740 270 : while (ptr != end) {
741 135 : switch (BYTE_TYPE(enc, ptr)) {
742 0 : CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
743 : case BT_GT:
744 0 : goto gt;
745 : case BT_SOL:
746 0 : goto sol;
747 : case BT_S: case BT_CR: case BT_LF:
748 0 : ptr += MINBPC(enc);
749 0 : continue;
750 : default:
751 0 : *nextTokPtr = ptr;
752 0 : return XML_TOK_INVALID;
753 : }
754 135 : return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
755 : }
756 0 : return XML_TOK_PARTIAL;
757 : }
758 : case BT_GT:
759 : gt:
760 11 : *nextTokPtr = ptr + MINBPC(enc);
761 11 : return XML_TOK_START_TAG_NO_ATTS;
762 : case BT_SOL:
763 : sol:
764 0 : ptr += MINBPC(enc);
765 0 : if (ptr == end)
766 0 : return XML_TOK_PARTIAL;
767 0 : if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
768 0 : *nextTokPtr = ptr;
769 0 : return XML_TOK_INVALID;
770 : }
771 0 : *nextTokPtr = ptr + MINBPC(enc);
772 0 : 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 690 : PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
783 : const char **nextTokPtr)
784 : {
785 690 : if (ptr == end)
786 0 : return XML_TOK_NONE;
787 : if (MINBPC(enc) > 1) {
788 690 : size_t n = end - ptr;
789 690 : 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 690 : switch (BYTE_TYPE(enc, ptr)) {
797 : case BT_LT:
798 207 : return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
799 : case BT_AMP:
800 0 : return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
801 : case BT_CR:
802 2 : ptr += MINBPC(enc);
803 2 : if (ptr == end)
804 0 : return XML_TOK_TRAILING_CR;
805 2 : if (BYTE_TYPE(enc, ptr) == BT_LF)
806 2 : ptr += MINBPC(enc);
807 2 : *nextTokPtr = ptr;
808 2 : return XML_TOK_DATA_NEWLINE;
809 : case BT_LF:
810 264 : *nextTokPtr = ptr + MINBPC(enc);
811 264 : 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 217 : ptr += MINBPC(enc);
830 217 : break;
831 : }
832 2750 : while (ptr != end) {
833 2533 : 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 0 : if (ptr + MINBPC(enc) != end) {
846 0 : if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
847 0 : ptr += MINBPC(enc);
848 0 : 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 217 : *nextTokPtr = ptr;
868 217 : return XML_TOK_DATA_CHARS;
869 : default:
870 2316 : ptr += MINBPC(enc);
871 2316 : break;
872 : }
873 : }
874 0 : *nextTokPtr = ptr;
875 0 : 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 0 : PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
911 : const char **nextTokPtr)
912 : {
913 0 : if (ptr == end)
914 0 : return XML_TOK_PARTIAL;
915 0 : 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 0 : while (ptr != end) {
922 0 : 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 0 : *nextTokPtr = ptr;
927 0 : 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 0 : PREFIX(scanLit)(int open, const ENCODING *enc,
938 : const char *ptr, const char *end,
939 : const char **nextTokPtr)
940 : {
941 0 : while (ptr != end) {
942 0 : int t = BYTE_TYPE(enc, ptr);
943 0 : switch (t) {
944 0 : INVALID_CASES(ptr, nextTokPtr)
945 : case BT_QUOT:
946 : case BT_APOS:
947 0 : ptr += MINBPC(enc);
948 0 : if (t != open)
949 0 : break;
950 0 : if (ptr == end)
951 0 : return -XML_TOK_LITERAL;
952 0 : *nextTokPtr = ptr;
953 0 : 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 0 : return XML_TOK_LITERAL;
957 : default:
958 0 : return XML_TOK_INVALID;
959 : }
960 : default:
961 0 : ptr += MINBPC(enc);
962 0 : break;
963 : }
964 : }
965 0 : return XML_TOK_PARTIAL;
966 : }
967 :
968 : static int PTRCALL
969 137 : PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
970 : const char **nextTokPtr)
971 : {
972 : int tok;
973 137 : if (ptr == end)
974 44 : return XML_TOK_NONE;
975 : if (MINBPC(enc) > 1) {
976 93 : size_t n = end - ptr;
977 93 : 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 93 : switch (BYTE_TYPE(enc, ptr)) {
985 : case BT_QUOT:
986 0 : return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
987 : case BT_APOS:
988 0 : return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
989 : case BT_LT:
990 : {
991 47 : ptr += MINBPC(enc);
992 47 : if (ptr == end)
993 0 : return XML_TOK_PARTIAL;
994 47 : switch (BYTE_TYPE(enc, ptr)) {
995 : case BT_EXCL:
996 21 : return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
997 : case BT_QUEST:
998 4 : 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 22 : *nextTokPtr = ptr - MINBPC(enc);
1006 22 : return XML_TOK_INSTANCE_START;
1007 : }
1008 0 : *nextTokPtr = ptr;
1009 0 : return XML_TOK_INVALID;
1010 : }
1011 : case BT_CR:
1012 1 : 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 54 : ptr += MINBPC(enc);
1021 50 : if (ptr == end)
1022 21 : break;
1023 29 : switch (BYTE_TYPE(enc, ptr)) {
1024 : case BT_S: case BT_LF:
1025 4 : break;
1026 : case BT_CR:
1027 : /* don't split CR/LF pair */
1028 0 : if (ptr + MINBPC(enc) != end)
1029 0 : break;
1030 : /* fall through */
1031 : default:
1032 25 : *nextTokPtr = ptr;
1033 25 : return XML_TOK_PROLOG_S;
1034 : }
1035 : }
1036 21 : *nextTokPtr = ptr;
1037 21 : 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 0 : *nextTokPtr = ptr + MINBPC(enc);
1045 0 : return XML_TOK_OPEN_BRACKET;
1046 : case BT_RSQB:
1047 0 : ptr += MINBPC(enc);
1048 0 : if (ptr == end)
1049 0 : return -XML_TOK_CLOSE_BRACKET;
1050 0 : 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 0 : *nextTokPtr = ptr;
1059 0 : 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 0 : *nextTokPtr = ptr + MINBPC(enc);
1090 0 : return XML_TOK_DECL_CLOSE;
1091 : case BT_NUM:
1092 0 : 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 0 : tok = XML_TOK_NAME;
1114 0 : ptr += MINBPC(enc);
1115 0 : 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 0 : while (ptr != end) {
1142 0 : 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 0 : *nextTokPtr = ptr;
1148 0 : return tok;
1149 : #ifdef XML_NS
1150 : case BT_COLON:
1151 0 : ptr += MINBPC(enc);
1152 0 : switch (tok) {
1153 : case XML_TOK_NAME:
1154 0 : if (ptr == end)
1155 0 : return XML_TOK_PARTIAL;
1156 0 : tok = XML_TOK_PREFIXED_NAME;
1157 0 : 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 0 : break;
1164 : case XML_TOK_PREFIXED_NAME:
1165 0 : tok = XML_TOK_NMTOKEN;
1166 0 : break;
1167 : }
1168 0 : 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 27 : PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
1201 : const char *end, const char **nextTokPtr)
1202 : {
1203 : const char *start;
1204 27 : if (ptr == end)
1205 1 : return XML_TOK_NONE;
1206 26 : start = ptr;
1207 732 : while (ptr != end) {
1208 705 : 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 0 : if (ptr == start)
1215 0 : return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
1216 0 : *nextTokPtr = ptr;
1217 0 : 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 10 : if (ptr == start) {
1224 5 : *nextTokPtr = ptr + MINBPC(enc);
1225 5 : return XML_TOK_DATA_NEWLINE;
1226 : }
1227 5 : *nextTokPtr = ptr;
1228 5 : 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 15 : if (ptr == start) {
1243 10 : *nextTokPtr = ptr + MINBPC(enc);
1244 10 : return XML_TOK_ATTRIBUTE_VALUE_S;
1245 : }
1246 5 : *nextTokPtr = ptr;
1247 5 : return XML_TOK_DATA_CHARS;
1248 : default:
1249 680 : ptr += MINBPC(enc);
1250 680 : break;
1251 : }
1252 : }
1253 1 : *nextTokPtr = ptr;
1254 1 : return XML_TOK_DATA_CHARS;
1255 : }
1256 :
1257 : static int PTRCALL
1258 0 : PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
1259 : const char *end, const char **nextTokPtr)
1260 : {
1261 : const char *start;
1262 0 : if (ptr == end)
1263 0 : return XML_TOK_NONE;
1264 0 : start = ptr;
1265 0 : while (ptr != end) {
1266 0 : 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 0 : if (ptr == start)
1273 0 : return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
1274 0 : *nextTokPtr = ptr;
1275 0 : 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 0 : if (ptr == start) {
1286 0 : *nextTokPtr = ptr + MINBPC(enc);
1287 0 : return XML_TOK_DATA_NEWLINE;
1288 : }
1289 0 : *nextTokPtr = ptr;
1290 0 : 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 0 : ptr += MINBPC(enc);
1305 0 : break;
1306 : }
1307 : }
1308 0 : *nextTokPtr = ptr;
1309 0 : 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 0 : PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
1369 : const char **badPtr)
1370 : {
1371 0 : ptr += MINBPC(enc);
1372 0 : end -= MINBPC(enc);
1373 0 : for (; ptr != end; ptr += MINBPC(enc)) {
1374 0 : 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 0 : break;
1397 : case BT_S:
1398 0 : if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
1399 0 : *badPtr = ptr;
1400 0 : return 0;
1401 : }
1402 0 : break;
1403 : case BT_NAME:
1404 : case BT_NMSTRT:
1405 0 : if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
1406 0 : break;
1407 : default:
1408 0 : switch (BYTE_TO_ASCII(enc, ptr)) {
1409 : case 0x24: /* $ */
1410 : case 0x40: /* @ */
1411 0 : break;
1412 : default:
1413 0 : *badPtr = ptr;
1414 0 : return 0;
1415 : }
1416 0 : break;
1417 : }
1418 : }
1419 0 : 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 146 : PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
1429 : int attsMax, ATTRIBUTE *atts)
1430 : {
1431 146 : enum { other, inName, inValue } state = inName;
1432 146 : int nAtts = 0;
1433 146 : int open = 0; /* defined when state == inValue;
1434 : initialization just to shut up compilers */
1435 :
1436 20499 : for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
1437 40852 : 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 6150 : START_NAME
1454 6150 : break;
1455 : #undef START_NAME
1456 : case BT_QUOT:
1457 714 : if (state != inValue) {
1458 357 : if (nAtts < attsMax)
1459 357 : atts[nAtts].valuePtr = ptr + MINBPC(enc);
1460 357 : state = inValue;
1461 357 : open = BT_QUOT;
1462 : }
1463 357 : else if (open == BT_QUOT) {
1464 357 : state = other;
1465 357 : if (nAtts < attsMax)
1466 357 : atts[nAtts].valueEnd = ptr;
1467 357 : nAtts++;
1468 : }
1469 714 : break;
1470 : case BT_APOS:
1471 0 : if (state != inValue) {
1472 0 : if (nAtts < attsMax)
1473 0 : atts[nAtts].valuePtr = ptr + MINBPC(enc);
1474 0 : state = inValue;
1475 0 : open = BT_APOS;
1476 : }
1477 0 : else if (open == BT_APOS) {
1478 0 : state = other;
1479 0 : if (nAtts < attsMax)
1480 0 : atts[nAtts].valueEnd = ptr;
1481 0 : nAtts++;
1482 : }
1483 0 : break;
1484 : case BT_AMP:
1485 0 : if (nAtts < attsMax)
1486 0 : atts[nAtts].normalized = 0;
1487 0 : break;
1488 : case BT_S:
1489 1399 : if (state == inName)
1490 135 : state = other;
1491 1264 : else if (state == inValue
1492 989 : && nAtts < attsMax
1493 989 : && atts[nAtts].normalized
1494 980 : && (ptr == atts[nAtts].valuePtr
1495 980 : || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
1496 980 : || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
1497 980 : || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
1498 0 : atts[nAtts].normalized = 0;
1499 1399 : 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 12 : if (state == inName)
1504 0 : state = other;
1505 12 : else if (state == inValue && nAtts < attsMax)
1506 5 : atts[nAtts].normalized = 0;
1507 12 : break;
1508 : case BT_GT:
1509 : case BT_SOL:
1510 270 : if (state != inValue)
1511 292 : return nAtts;
1512 124 : break;
1513 : default:
1514 11954 : break;
1515 : }
1516 : }
1517 : /* not reached */
1518 : }
1519 :
1520 : static int PTRFASTCALL
1521 0 : PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
1522 : {
1523 0 : int result = 0;
1524 : /* skip &# */
1525 0 : ptr += 2*MINBPC(enc);
1526 0 : if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
1527 0 : for (ptr += MINBPC(enc);
1528 0 : !CHAR_MATCHES(enc, ptr, ASCII_SEMI);
1529 0 : ptr += MINBPC(enc)) {
1530 0 : int c = BYTE_TO_ASCII(enc, ptr);
1531 0 : 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 0 : result <<= 4;
1535 0 : result |= (c - ASCII_0);
1536 0 : 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 0 : result <<= 4;
1545 0 : result += 10 + (c - ASCII_a);
1546 0 : break;
1547 : }
1548 0 : if (result >= 0x110000)
1549 0 : return -1;
1550 : }
1551 : }
1552 : else {
1553 0 : for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
1554 0 : int c = BYTE_TO_ASCII(enc, ptr);
1555 0 : result *= 10;
1556 0 : result += (c - ASCII_0);
1557 0 : if (result >= 0x110000)
1558 0 : return -1;
1559 : }
1560 : }
1561 0 : return checkCharRefNumber(result);
1562 : }
1563 :
1564 : static int PTRCALL
1565 0 : PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
1566 : const char *end)
1567 : {
1568 0 : switch ((end - ptr)/MINBPC(enc)) {
1569 : case 2:
1570 0 : if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
1571 0 : switch (BYTE_TO_ASCII(enc, ptr)) {
1572 : case ASCII_l:
1573 0 : return ASCII_LT;
1574 : case ASCII_g:
1575 0 : return ASCII_GT;
1576 : }
1577 : }
1578 0 : break;
1579 : case 3:
1580 0 : if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
1581 0 : ptr += MINBPC(enc);
1582 0 : if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
1583 0 : ptr += MINBPC(enc);
1584 0 : if (CHAR_MATCHES(enc, ptr, ASCII_p))
1585 0 : return ASCII_AMP;
1586 : }
1587 : }
1588 0 : break;
1589 : case 4:
1590 0 : switch (BYTE_TO_ASCII(enc, ptr)) {
1591 : case ASCII_q:
1592 0 : ptr += MINBPC(enc);
1593 0 : if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
1594 0 : ptr += MINBPC(enc);
1595 0 : if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
1596 0 : ptr += MINBPC(enc);
1597 0 : if (CHAR_MATCHES(enc, ptr, ASCII_t))
1598 0 : return ASCII_QUOT;
1599 : }
1600 : }
1601 0 : break;
1602 : case ASCII_a:
1603 0 : ptr += MINBPC(enc);
1604 0 : if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
1605 0 : ptr += MINBPC(enc);
1606 0 : if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
1607 0 : ptr += MINBPC(enc);
1608 0 : if (CHAR_MATCHES(enc, ptr, ASCII_s))
1609 0 : return ASCII_APOS;
1610 : }
1611 : }
1612 0 : break;
1613 : }
1614 : }
1615 0 : 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 : }
1679 : /* not reached */
1680 : }
1681 :
1682 : static int PTRCALL
1683 11 : PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
1684 : const char *end1, const char *ptr2)
1685 : {
1686 75 : for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
1687 64 : if (ptr1 == end1)
1688 0 : return 0;
1689 64 : if (!CHAR_MATCHES(enc, ptr1, *ptr2))
1690 0 : return 0;
1691 : }
1692 11 : return ptr1 == end1;
1693 : }
1694 :
1695 : static int PTRFASTCALL
1696 565 : PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
1697 : {
1698 565 : const char *start = ptr;
1699 : for (;;) {
1700 6197 : 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 2816 : ptr += MINBPC(enc);
1715 2816 : break;
1716 : default:
1717 1130 : return (int)(ptr - start);
1718 : }
1719 : }
1720 : }
1721 :
1722 : static const char * PTRFASTCALL
1723 0 : PREFIX(skipS)(const ENCODING *enc, const char *ptr)
1724 : {
1725 : for (;;) {
1726 0 : switch (BYTE_TYPE(enc, ptr)) {
1727 : case BT_LF:
1728 : case BT_CR:
1729 : case BT_S:
1730 0 : ptr += MINBPC(enc);
1731 0 : break;
1732 : default:
1733 0 : return ptr;
1734 : }
1735 : }
1736 : }
1737 :
1738 : static void PTRCALL
1739 168 : PREFIX(updatePosition)(const ENCODING *enc,
1740 : const char *ptr,
1741 : const char *end,
1742 : POSITION *pos)
1743 : {
1744 29336 : while (ptr != end) {
1745 29000 : 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 368 : pos->columnNumber = (XML_Size)-1;
1754 368 : pos->lineNumber++;
1755 368 : ptr += MINBPC(enc);
1756 368 : break;
1757 : case BT_CR:
1758 5 : pos->lineNumber++;
1759 5 : ptr += MINBPC(enc);
1760 5 : if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
1761 5 : ptr += MINBPC(enc);
1762 5 : pos->columnNumber = (XML_Size)-1;
1763 5 : break;
1764 : default:
1765 28627 : ptr += MINBPC(enc);
1766 28627 : break;
1767 : }
1768 29000 : pos->columnNumber++;
1769 : }
1770 168 : }
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 :
|