1 /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
5 /* This file is included! */
8 #ifndef IS_INVALID_CHAR
9 #define IS_INVALID_CHAR(enc, ptr, n) (0)
12 #define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
15 return XML_TOK_PARTIAL_CHAR; \
16 if (IS_INVALID_CHAR(enc, ptr, n)) { \
17 *(nextTokPtr) = (ptr); \
18 return XML_TOK_INVALID; \
23 #define INVALID_CASES(ptr, nextTokPtr) \
24 INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
25 INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
26 INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
30 *(nextTokPtr) = (ptr); \
31 return XML_TOK_INVALID;
33 #define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
36 return XML_TOK_PARTIAL_CHAR; \
37 if (!IS_NAME_CHAR(enc, ptr, n)) { \
39 return XML_TOK_INVALID; \
44 #define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
46 if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
48 return XML_TOK_INVALID; \
57 CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
58 CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
59 CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
61 #define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
64 return XML_TOK_PARTIAL_CHAR; \
65 if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
67 return XML_TOK_INVALID; \
72 #define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
74 if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
76 return XML_TOK_INVALID; \
82 CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
83 CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
84 CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
87 #define PREFIX(ident) ident
90 /* ptr points to character following "<!-" */
93 PREFIX(scanComment
)(const ENCODING
*enc
, const char *ptr
,
94 const char *end
, const char **nextTokPtr
)
97 if (!CHAR_MATCHES(enc
, ptr
, ASCII_MINUS
)) {
99 return XML_TOK_INVALID
;
103 switch (BYTE_TYPE(enc
, ptr
)) {
104 INVALID_CASES(ptr
, nextTokPtr
)
106 if ((ptr
+= MINBPC(enc
)) == end
)
107 return XML_TOK_PARTIAL
;
108 if (CHAR_MATCHES(enc
, ptr
, ASCII_MINUS
)) {
109 if ((ptr
+= MINBPC(enc
)) == end
)
110 return XML_TOK_PARTIAL
;
111 if (!CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
113 return XML_TOK_INVALID
;
115 *nextTokPtr
= ptr
+ MINBPC(enc
);
116 return XML_TOK_COMMENT
;
125 return XML_TOK_PARTIAL
;
128 /* ptr points to character following "<!" */
131 PREFIX(scanDecl
)(const ENCODING
*enc
, const char *ptr
,
132 const char *end
, const char **nextTokPtr
)
135 return XML_TOK_PARTIAL
;
136 switch (BYTE_TYPE(enc
, ptr
)) {
138 return PREFIX(scanComment
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
140 *nextTokPtr
= ptr
+ MINBPC(enc
);
141 return XML_TOK_COND_SECT_OPEN
;
148 return XML_TOK_INVALID
;
151 switch (BYTE_TYPE(enc
, ptr
)) {
153 if (ptr
+ MINBPC(enc
) == end
)
154 return XML_TOK_PARTIAL
;
155 /* don't allow <!ENTITY% foo "whatever"> */
156 switch (BYTE_TYPE(enc
, ptr
+ MINBPC(enc
))) {
157 case BT_S
: case BT_CR
: case BT_LF
: case BT_PERCNT
:
159 return XML_TOK_INVALID
;
162 case BT_S
: case BT_CR
: case BT_LF
:
164 return XML_TOK_DECL_OPEN
;
171 return XML_TOK_INVALID
;
174 return XML_TOK_PARTIAL
;
178 PREFIX(checkPiTarget
)(const ENCODING
*enc
, const char *ptr
,
179 const char *end
, int *tokPtr
)
182 *tokPtr
= XML_TOK_PI
;
183 if (end
- ptr
!= MINBPC(enc
)*3)
185 switch (BYTE_TO_ASCII(enc
, ptr
)) {
195 switch (BYTE_TO_ASCII(enc
, ptr
)) {
205 switch (BYTE_TO_ASCII(enc
, ptr
)) {
216 *tokPtr
= XML_TOK_XML_DECL
;
220 /* ptr points to character following "<?" */
223 PREFIX(scanPi
)(const ENCODING
*enc
, const char *ptr
,
224 const char *end
, const char **nextTokPtr
)
227 const char *target
= ptr
;
229 return XML_TOK_PARTIAL
;
230 switch (BYTE_TYPE(enc
, ptr
)) {
231 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
234 return XML_TOK_INVALID
;
237 switch (BYTE_TYPE(enc
, ptr
)) {
238 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
239 case BT_S
: case BT_CR
: case BT_LF
:
240 if (!PREFIX(checkPiTarget
)(enc
, target
, ptr
, &tok
)) {
242 return XML_TOK_INVALID
;
246 switch (BYTE_TYPE(enc
, ptr
)) {
247 INVALID_CASES(ptr
, nextTokPtr
)
251 return XML_TOK_PARTIAL
;
252 if (CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
253 *nextTokPtr
= ptr
+ MINBPC(enc
);
262 return XML_TOK_PARTIAL
;
264 if (!PREFIX(checkPiTarget
)(enc
, target
, ptr
, &tok
)) {
266 return XML_TOK_INVALID
;
270 return XML_TOK_PARTIAL
;
271 if (CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
272 *nextTokPtr
= ptr
+ MINBPC(enc
);
278 return XML_TOK_INVALID
;
281 return XML_TOK_PARTIAL
;
285 PREFIX(scanCdataSection
)(const ENCODING
*enc
, const char *ptr
,
286 const char *end
, const char **nextTokPtr
)
288 static const char CDATA_LSQB
[] = { ASCII_C
, ASCII_D
, ASCII_A
,
289 ASCII_T
, ASCII_A
, ASCII_LSQB
};
292 if (end
- ptr
< 6 * MINBPC(enc
))
293 return XML_TOK_PARTIAL
;
294 for (i
= 0; i
< 6; i
++, ptr
+= MINBPC(enc
)) {
295 if (!CHAR_MATCHES(enc
, ptr
, CDATA_LSQB
[i
])) {
297 return XML_TOK_INVALID
;
301 return XML_TOK_CDATA_SECT_OPEN
;
305 PREFIX(cdataSectionTok
)(const ENCODING
*enc
, const char *ptr
,
306 const char *end
, const char **nextTokPtr
)
310 if (MINBPC(enc
) > 1) {
311 size_t n
= end
- ptr
;
312 if (n
& (MINBPC(enc
) - 1)) {
313 n
&= ~(MINBPC(enc
) - 1);
315 return XML_TOK_PARTIAL
;
319 switch (BYTE_TYPE(enc
, ptr
)) {
323 return XML_TOK_PARTIAL
;
324 if (!CHAR_MATCHES(enc
, ptr
, ASCII_RSQB
))
328 return XML_TOK_PARTIAL
;
329 if (!CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
333 *nextTokPtr
= ptr
+ MINBPC(enc
);
334 return XML_TOK_CDATA_SECT_CLOSE
;
338 return XML_TOK_PARTIAL
;
339 if (BYTE_TYPE(enc
, ptr
) == BT_LF
)
342 return XML_TOK_DATA_NEWLINE
;
344 *nextTokPtr
= ptr
+ MINBPC(enc
);
345 return XML_TOK_DATA_NEWLINE
;
346 INVALID_CASES(ptr
, nextTokPtr
)
352 switch (BYTE_TYPE(enc
, ptr
)) {
353 #define LEAD_CASE(n) \
355 if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
357 return XML_TOK_DATA_CHARS; \
361 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
370 return XML_TOK_DATA_CHARS
;
377 return XML_TOK_DATA_CHARS
;
380 /* ptr points to character following "</" */
383 PREFIX(scanEndTag
)(const ENCODING
*enc
, const char *ptr
,
384 const char *end
, const char **nextTokPtr
)
387 return XML_TOK_PARTIAL
;
388 switch (BYTE_TYPE(enc
, ptr
)) {
389 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
392 return XML_TOK_INVALID
;
395 switch (BYTE_TYPE(enc
, ptr
)) {
396 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
397 case BT_S
: case BT_CR
: case BT_LF
:
398 for (ptr
+= MINBPC(enc
); ptr
!= end
; ptr
+= MINBPC(enc
)) {
399 switch (BYTE_TYPE(enc
, ptr
)) {
400 case BT_S
: case BT_CR
: case BT_LF
:
403 *nextTokPtr
= ptr
+ MINBPC(enc
);
404 return XML_TOK_END_TAG
;
407 return XML_TOK_INVALID
;
410 return XML_TOK_PARTIAL
;
413 /* no need to check qname syntax here,
414 since end-tag must match exactly */
419 *nextTokPtr
= ptr
+ MINBPC(enc
);
420 return XML_TOK_END_TAG
;
423 return XML_TOK_INVALID
;
426 return XML_TOK_PARTIAL
;
429 /* ptr points to character following "&#X" */
432 PREFIX(scanHexCharRef
)(const ENCODING
*enc
, const char *ptr
,
433 const char *end
, const char **nextTokPtr
)
436 switch (BYTE_TYPE(enc
, ptr
)) {
442 return XML_TOK_INVALID
;
444 for (ptr
+= MINBPC(enc
); ptr
!= end
; ptr
+= MINBPC(enc
)) {
445 switch (BYTE_TYPE(enc
, ptr
)) {
450 *nextTokPtr
= ptr
+ MINBPC(enc
);
451 return XML_TOK_CHAR_REF
;
454 return XML_TOK_INVALID
;
458 return XML_TOK_PARTIAL
;
461 /* ptr points to character following "&#" */
464 PREFIX(scanCharRef
)(const ENCODING
*enc
, const char *ptr
,
465 const char *end
, const char **nextTokPtr
)
468 if (CHAR_MATCHES(enc
, ptr
, ASCII_x
))
469 return PREFIX(scanHexCharRef
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
470 switch (BYTE_TYPE(enc
, ptr
)) {
475 return XML_TOK_INVALID
;
477 for (ptr
+= MINBPC(enc
); ptr
!= end
; ptr
+= MINBPC(enc
)) {
478 switch (BYTE_TYPE(enc
, ptr
)) {
482 *nextTokPtr
= ptr
+ MINBPC(enc
);
483 return XML_TOK_CHAR_REF
;
486 return XML_TOK_INVALID
;
490 return XML_TOK_PARTIAL
;
493 /* ptr points to character following "&" */
496 PREFIX(scanRef
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
497 const char **nextTokPtr
)
500 return XML_TOK_PARTIAL
;
501 switch (BYTE_TYPE(enc
, ptr
)) {
502 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
504 return PREFIX(scanCharRef
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
507 return XML_TOK_INVALID
;
510 switch (BYTE_TYPE(enc
, ptr
)) {
511 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
513 *nextTokPtr
= ptr
+ MINBPC(enc
);
514 return XML_TOK_ENTITY_REF
;
517 return XML_TOK_INVALID
;
520 return XML_TOK_PARTIAL
;
523 /* ptr points to character following first character of attribute name */
526 PREFIX(scanAtts
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
527 const char **nextTokPtr
)
533 switch (BYTE_TYPE(enc
, ptr
)) {
534 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
539 return XML_TOK_INVALID
;
544 return XML_TOK_PARTIAL
;
545 switch (BYTE_TYPE(enc
, ptr
)) {
546 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
549 return XML_TOK_INVALID
;
553 case BT_S
: case BT_CR
: case BT_LF
:
559 return XML_TOK_PARTIAL
;
560 t
= BYTE_TYPE(enc
, ptr
);
570 return XML_TOK_INVALID
;
583 return XML_TOK_PARTIAL
;
584 open
= BYTE_TYPE(enc
, ptr
);
585 if (open
== BT_QUOT
|| open
== BT_APOS
)
594 return XML_TOK_INVALID
;
598 /* in attribute value */
602 return XML_TOK_PARTIAL
;
603 t
= BYTE_TYPE(enc
, ptr
);
607 INVALID_CASES(ptr
, nextTokPtr
)
610 int tok
= PREFIX(scanRef
)(enc
, ptr
+ MINBPC(enc
), end
, &ptr
);
612 if (tok
== XML_TOK_INVALID
)
620 return XML_TOK_INVALID
;
628 return XML_TOK_PARTIAL
;
629 switch (BYTE_TYPE(enc
, ptr
)) {
640 return XML_TOK_INVALID
;
642 /* ptr points to closing quote */
646 return XML_TOK_PARTIAL
;
647 switch (BYTE_TYPE(enc
, ptr
)) {
648 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
649 case BT_S
: case BT_CR
: case BT_LF
:
653 *nextTokPtr
= ptr
+ MINBPC(enc
);
654 return XML_TOK_START_TAG_WITH_ATTS
;
659 return XML_TOK_PARTIAL
;
660 if (!CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
662 return XML_TOK_INVALID
;
664 *nextTokPtr
= ptr
+ MINBPC(enc
);
665 return XML_TOK_EMPTY_ELEMENT_WITH_ATTS
;
668 return XML_TOK_INVALID
;
676 return XML_TOK_INVALID
;
679 return XML_TOK_PARTIAL
;
682 /* ptr points to character following "<" */
685 PREFIX(scanLt
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
686 const char **nextTokPtr
)
692 return XML_TOK_PARTIAL
;
693 switch (BYTE_TYPE(enc
, ptr
)) {
694 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
696 if ((ptr
+= MINBPC(enc
)) == end
)
697 return XML_TOK_PARTIAL
;
698 switch (BYTE_TYPE(enc
, ptr
)) {
700 return PREFIX(scanComment
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
702 return PREFIX(scanCdataSection
)(enc
, ptr
+ MINBPC(enc
),
706 return XML_TOK_INVALID
;
708 return PREFIX(scanPi
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
710 return PREFIX(scanEndTag
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
713 return XML_TOK_INVALID
;
718 /* we have a start-tag */
720 switch (BYTE_TYPE(enc
, ptr
)) {
721 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
726 return XML_TOK_INVALID
;
731 return XML_TOK_PARTIAL
;
732 switch (BYTE_TYPE(enc
, ptr
)) {
733 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
736 return XML_TOK_INVALID
;
740 case BT_S
: case BT_CR
: case BT_LF
:
744 switch (BYTE_TYPE(enc
, ptr
)) {
745 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
750 case BT_S
: case BT_CR
: case BT_LF
:
755 return XML_TOK_INVALID
;
757 return PREFIX(scanAtts
)(enc
, ptr
, end
, nextTokPtr
);
759 return XML_TOK_PARTIAL
;
763 *nextTokPtr
= ptr
+ MINBPC(enc
);
764 return XML_TOK_START_TAG_NO_ATTS
;
769 return XML_TOK_PARTIAL
;
770 if (!CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
772 return XML_TOK_INVALID
;
774 *nextTokPtr
= ptr
+ MINBPC(enc
);
775 return XML_TOK_EMPTY_ELEMENT_NO_ATTS
;
778 return XML_TOK_INVALID
;
781 return XML_TOK_PARTIAL
;
785 PREFIX(contentTok
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
786 const char **nextTokPtr
)
790 if (MINBPC(enc
) > 1) {
791 size_t n
= end
- ptr
;
792 if (n
& (MINBPC(enc
) - 1)) {
793 n
&= ~(MINBPC(enc
) - 1);
795 return XML_TOK_PARTIAL
;
799 switch (BYTE_TYPE(enc
, ptr
)) {
801 return PREFIX(scanLt
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
803 return PREFIX(scanRef
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
807 return XML_TOK_TRAILING_CR
;
808 if (BYTE_TYPE(enc
, ptr
) == BT_LF
)
811 return XML_TOK_DATA_NEWLINE
;
813 *nextTokPtr
= ptr
+ MINBPC(enc
);
814 return XML_TOK_DATA_NEWLINE
;
818 return XML_TOK_TRAILING_RSQB
;
819 if (!CHAR_MATCHES(enc
, ptr
, ASCII_RSQB
))
823 return XML_TOK_TRAILING_RSQB
;
824 if (!CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
829 return XML_TOK_INVALID
;
830 INVALID_CASES(ptr
, nextTokPtr
)
836 switch (BYTE_TYPE(enc
, ptr
)) {
837 #define LEAD_CASE(n) \
839 if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
841 return XML_TOK_DATA_CHARS; \
845 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
848 if (ptr
+ MINBPC(enc
) != end
) {
849 if (!CHAR_MATCHES(enc
, ptr
+ MINBPC(enc
), ASCII_RSQB
)) {
853 if (ptr
+ 2*MINBPC(enc
) != end
) {
854 if (!CHAR_MATCHES(enc
, ptr
+ 2*MINBPC(enc
), ASCII_GT
)) {
858 *nextTokPtr
= ptr
+ 2*MINBPC(enc
);
859 return XML_TOK_INVALID
;
871 return XML_TOK_DATA_CHARS
;
878 return XML_TOK_DATA_CHARS
;
881 /* ptr points to character following "%" */
884 PREFIX(scanPercent
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
885 const char **nextTokPtr
)
888 return -XML_TOK_PERCENT
;
889 switch (BYTE_TYPE(enc
, ptr
)) {
890 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
891 case BT_S
: case BT_LF
: case BT_CR
: case BT_PERCNT
:
893 return XML_TOK_PERCENT
;
896 return XML_TOK_INVALID
;
899 switch (BYTE_TYPE(enc
, ptr
)) {
900 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
902 *nextTokPtr
= ptr
+ MINBPC(enc
);
903 return XML_TOK_PARAM_ENTITY_REF
;
906 return XML_TOK_INVALID
;
909 return XML_TOK_PARTIAL
;
913 PREFIX(scanPoundName
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
914 const char **nextTokPtr
)
917 return XML_TOK_PARTIAL
;
918 switch (BYTE_TYPE(enc
, ptr
)) {
919 CHECK_NMSTRT_CASES(enc
, ptr
, end
, nextTokPtr
)
922 return XML_TOK_INVALID
;
925 switch (BYTE_TYPE(enc
, ptr
)) {
926 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
927 case BT_CR
: case BT_LF
: case BT_S
:
928 case BT_RPAR
: case BT_GT
: case BT_PERCNT
: case BT_VERBAR
:
930 return XML_TOK_POUND_NAME
;
933 return XML_TOK_INVALID
;
936 return -XML_TOK_POUND_NAME
;
940 PREFIX(scanLit
)(int open
, const ENCODING
*enc
,
941 const char *ptr
, const char *end
,
942 const char **nextTokPtr
)
945 int t
= BYTE_TYPE(enc
, ptr
);
947 INVALID_CASES(ptr
, nextTokPtr
)
954 return -XML_TOK_LITERAL
;
956 switch (BYTE_TYPE(enc
, ptr
)) {
957 case BT_S
: case BT_CR
: case BT_LF
:
958 case BT_GT
: case BT_PERCNT
: case BT_LSQB
:
959 return XML_TOK_LITERAL
;
961 return XML_TOK_INVALID
;
968 return XML_TOK_PARTIAL
;
972 PREFIX(prologTok
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
973 const char **nextTokPtr
)
978 if (MINBPC(enc
) > 1) {
979 size_t n
= end
- ptr
;
980 if (n
& (MINBPC(enc
) - 1)) {
981 n
&= ~(MINBPC(enc
) - 1);
983 return XML_TOK_PARTIAL
;
987 switch (BYTE_TYPE(enc
, ptr
)) {
989 return PREFIX(scanLit
)(BT_QUOT
, enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
991 return PREFIX(scanLit
)(BT_APOS
, enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
996 return XML_TOK_PARTIAL
;
997 switch (BYTE_TYPE(enc
, ptr
)) {
999 return PREFIX(scanDecl
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
1001 return PREFIX(scanPi
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
1008 *nextTokPtr
= ptr
- MINBPC(enc
);
1009 return XML_TOK_INSTANCE_START
;
1012 return XML_TOK_INVALID
;
1015 if (ptr
+ MINBPC(enc
) == end
) {
1017 /* indicate that this might be part of a CR/LF pair */
1018 return -XML_TOK_PROLOG_S
;
1021 case BT_S
: case BT_LF
:
1026 switch (BYTE_TYPE(enc
, ptr
)) {
1027 case BT_S
: case BT_LF
:
1030 /* don't split CR/LF pair */
1031 if (ptr
+ MINBPC(enc
) != end
)
1036 return XML_TOK_PROLOG_S
;
1040 return XML_TOK_PROLOG_S
;
1042 return PREFIX(scanPercent
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
1044 *nextTokPtr
= ptr
+ MINBPC(enc
);
1045 return XML_TOK_COMMA
;
1047 *nextTokPtr
= ptr
+ MINBPC(enc
);
1048 return XML_TOK_OPEN_BRACKET
;
1052 return -XML_TOK_CLOSE_BRACKET
;
1053 if (CHAR_MATCHES(enc
, ptr
, ASCII_RSQB
)) {
1054 if (ptr
+ MINBPC(enc
) == end
)
1055 return XML_TOK_PARTIAL
;
1056 if (CHAR_MATCHES(enc
, ptr
+ MINBPC(enc
), ASCII_GT
)) {
1057 *nextTokPtr
= ptr
+ 2*MINBPC(enc
);
1058 return XML_TOK_COND_SECT_CLOSE
;
1062 return XML_TOK_CLOSE_BRACKET
;
1064 *nextTokPtr
= ptr
+ MINBPC(enc
);
1065 return XML_TOK_OPEN_PAREN
;
1069 return -XML_TOK_CLOSE_PAREN
;
1070 switch (BYTE_TYPE(enc
, ptr
)) {
1072 *nextTokPtr
= ptr
+ MINBPC(enc
);
1073 return XML_TOK_CLOSE_PAREN_ASTERISK
;
1075 *nextTokPtr
= ptr
+ MINBPC(enc
);
1076 return XML_TOK_CLOSE_PAREN_QUESTION
;
1078 *nextTokPtr
= ptr
+ MINBPC(enc
);
1079 return XML_TOK_CLOSE_PAREN_PLUS
;
1080 case BT_CR
: case BT_LF
: case BT_S
:
1081 case BT_GT
: case BT_COMMA
: case BT_VERBAR
:
1084 return XML_TOK_CLOSE_PAREN
;
1087 return XML_TOK_INVALID
;
1089 *nextTokPtr
= ptr
+ MINBPC(enc
);
1092 *nextTokPtr
= ptr
+ MINBPC(enc
);
1093 return XML_TOK_DECL_CLOSE
;
1095 return PREFIX(scanPoundName
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
1096 #define LEAD_CASE(n) \
1097 case BT_LEAD ## n: \
1098 if (end - ptr < n) \
1099 return XML_TOK_PARTIAL_CHAR; \
1100 if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
1102 tok = XML_TOK_NAME; \
1105 if (IS_NAME_CHAR(enc, ptr, n)) { \
1107 tok = XML_TOK_NMTOKEN; \
1110 *nextTokPtr = ptr; \
1111 return XML_TOK_INVALID;
1112 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
1125 tok
= XML_TOK_NMTOKEN
;
1129 if (IS_NMSTRT_CHAR_MINBPC(enc
, ptr
)) {
1134 if (IS_NAME_CHAR_MINBPC(enc
, ptr
)) {
1136 tok
= XML_TOK_NMTOKEN
;
1142 return XML_TOK_INVALID
;
1144 while (ptr
!= end
) {
1145 switch (BYTE_TYPE(enc
, ptr
)) {
1146 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
1147 case BT_GT
: case BT_RPAR
: case BT_COMMA
:
1148 case BT_VERBAR
: case BT_LSQB
: case BT_PERCNT
:
1149 case BT_S
: case BT_CR
: case BT_LF
:
1158 return XML_TOK_PARTIAL
;
1159 tok
= XML_TOK_PREFIXED_NAME
;
1160 switch (BYTE_TYPE(enc
, ptr
)) {
1161 CHECK_NAME_CASES(enc
, ptr
, end
, nextTokPtr
)
1163 tok
= XML_TOK_NMTOKEN
;
1167 case XML_TOK_PREFIXED_NAME
:
1168 tok
= XML_TOK_NMTOKEN
;
1174 if (tok
== XML_TOK_NMTOKEN
) {
1176 return XML_TOK_INVALID
;
1178 *nextTokPtr
= ptr
+ MINBPC(enc
);
1179 return XML_TOK_NAME_PLUS
;
1181 if (tok
== XML_TOK_NMTOKEN
) {
1183 return XML_TOK_INVALID
;
1185 *nextTokPtr
= ptr
+ MINBPC(enc
);
1186 return XML_TOK_NAME_ASTERISK
;
1188 if (tok
== XML_TOK_NMTOKEN
) {
1190 return XML_TOK_INVALID
;
1192 *nextTokPtr
= ptr
+ MINBPC(enc
);
1193 return XML_TOK_NAME_QUESTION
;
1196 return XML_TOK_INVALID
;
1203 PREFIX(attributeValueTok
)(const ENCODING
*enc
, const char *ptr
,
1204 const char *end
, const char **nextTokPtr
)
1208 return XML_TOK_NONE
;
1210 while (ptr
!= end
) {
1211 switch (BYTE_TYPE(enc
, ptr
)) {
1212 #define LEAD_CASE(n) \
1213 case BT_LEAD ## n: ptr += n; break;
1214 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
1218 return PREFIX(scanRef
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
1220 return XML_TOK_DATA_CHARS
;
1222 /* this is for inside entity references */
1224 return XML_TOK_INVALID
;
1227 *nextTokPtr
= ptr
+ MINBPC(enc
);
1228 return XML_TOK_DATA_NEWLINE
;
1231 return XML_TOK_DATA_CHARS
;
1236 return XML_TOK_TRAILING_CR
;
1237 if (BYTE_TYPE(enc
, ptr
) == BT_LF
)
1240 return XML_TOK_DATA_NEWLINE
;
1243 return XML_TOK_DATA_CHARS
;
1246 *nextTokPtr
= ptr
+ MINBPC(enc
);
1247 return XML_TOK_ATTRIBUTE_VALUE_S
;
1250 return XML_TOK_DATA_CHARS
;
1257 return XML_TOK_DATA_CHARS
;
1261 PREFIX(entityValueTok
)(const ENCODING
*enc
, const char *ptr
,
1262 const char *end
, const char **nextTokPtr
)
1266 return XML_TOK_NONE
;
1268 while (ptr
!= end
) {
1269 switch (BYTE_TYPE(enc
, ptr
)) {
1270 #define LEAD_CASE(n) \
1271 case BT_LEAD ## n: ptr += n; break;
1272 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
1276 return PREFIX(scanRef
)(enc
, ptr
+ MINBPC(enc
), end
, nextTokPtr
);
1278 return XML_TOK_DATA_CHARS
;
1281 int tok
= PREFIX(scanPercent
)(enc
, ptr
+ MINBPC(enc
),
1283 return (tok
== XML_TOK_PERCENT
) ? XML_TOK_INVALID
: tok
;
1286 return XML_TOK_DATA_CHARS
;
1289 *nextTokPtr
= ptr
+ MINBPC(enc
);
1290 return XML_TOK_DATA_NEWLINE
;
1293 return XML_TOK_DATA_CHARS
;
1298 return XML_TOK_TRAILING_CR
;
1299 if (BYTE_TYPE(enc
, ptr
) == BT_LF
)
1302 return XML_TOK_DATA_NEWLINE
;
1305 return XML_TOK_DATA_CHARS
;
1312 return XML_TOK_DATA_CHARS
;
1318 PREFIX(ignoreSectionTok
)(const ENCODING
*enc
, const char *ptr
,
1319 const char *end
, const char **nextTokPtr
)
1322 if (MINBPC(enc
) > 1) {
1323 size_t n
= end
- ptr
;
1324 if (n
& (MINBPC(enc
) - 1)) {
1325 n
&= ~(MINBPC(enc
) - 1);
1329 while (ptr
!= end
) {
1330 switch (BYTE_TYPE(enc
, ptr
)) {
1331 INVALID_CASES(ptr
, nextTokPtr
)
1333 if ((ptr
+= MINBPC(enc
)) == end
)
1334 return XML_TOK_PARTIAL
;
1335 if (CHAR_MATCHES(enc
, ptr
, ASCII_EXCL
)) {
1336 if ((ptr
+= MINBPC(enc
)) == end
)
1337 return XML_TOK_PARTIAL
;
1338 if (CHAR_MATCHES(enc
, ptr
, ASCII_LSQB
)) {
1345 if ((ptr
+= MINBPC(enc
)) == end
)
1346 return XML_TOK_PARTIAL
;
1347 if (CHAR_MATCHES(enc
, ptr
, ASCII_RSQB
)) {
1348 if ((ptr
+= MINBPC(enc
)) == end
)
1349 return XML_TOK_PARTIAL
;
1350 if (CHAR_MATCHES(enc
, ptr
, ASCII_GT
)) {
1354 return XML_TOK_IGNORE_SECT
;
1365 return XML_TOK_PARTIAL
;
1368 #endif /* XML_DTD */
1371 PREFIX(isPublicId
)(const ENCODING
*enc
, const char *ptr
, const char *end
,
1372 const char **badPtr
)
1376 for (; ptr
!= end
; ptr
+= MINBPC(enc
)) {
1377 switch (BYTE_TYPE(enc
, ptr
)) {
1401 if (CHAR_MATCHES(enc
, ptr
, ASCII_TAB
)) {
1408 if (!(BYTE_TO_ASCII(enc
, ptr
) & ~0x7f))
1411 switch (BYTE_TO_ASCII(enc
, ptr
)) {
1425 /* This must only be called for a well-formed start-tag or empty
1426 element tag. Returns the number of attributes. Pointers to the
1427 first attsMax attributes are stored in atts.
1431 PREFIX(getAtts
)(const ENCODING
*enc
, const char *ptr
,
1432 int attsMax
, ATTRIBUTE
*atts
)
1434 enum { other
, inName
, inValue
} state
= inName
;
1436 int open
= 0; /* defined when state == inValue;
1437 initialization just to shut up compilers */
1439 for (ptr
+= MINBPC(enc
);; ptr
+= MINBPC(enc
)) {
1440 switch (BYTE_TYPE(enc
, ptr
)) {
1441 #define START_NAME \
1442 if (state == other) { \
1443 if (nAtts < attsMax) { \
1444 atts[nAtts].name = ptr; \
1445 atts[nAtts].normalized = 1; \
1449 #define LEAD_CASE(n) \
1450 case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
1451 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
1460 if (state
!= inValue
) {
1461 if (nAtts
< attsMax
)
1462 atts
[nAtts
].valuePtr
= ptr
+ MINBPC(enc
);
1466 else if (open
== BT_QUOT
) {
1468 if (nAtts
< attsMax
)
1469 atts
[nAtts
].valueEnd
= ptr
;
1474 if (state
!= inValue
) {
1475 if (nAtts
< attsMax
)
1476 atts
[nAtts
].valuePtr
= ptr
+ MINBPC(enc
);
1480 else if (open
== BT_APOS
) {
1482 if (nAtts
< attsMax
)
1483 atts
[nAtts
].valueEnd
= ptr
;
1488 if (nAtts
< attsMax
)
1489 atts
[nAtts
].normalized
= 0;
1492 if (state
== inName
)
1494 else if (state
== inValue
1496 && atts
[nAtts
].normalized
1497 && (ptr
== atts
[nAtts
].valuePtr
1498 || BYTE_TO_ASCII(enc
, ptr
) != ASCII_SPACE
1499 || BYTE_TO_ASCII(enc
, ptr
+ MINBPC(enc
)) == ASCII_SPACE
1500 || BYTE_TYPE(enc
, ptr
+ MINBPC(enc
)) == open
))
1501 atts
[nAtts
].normalized
= 0;
1503 case BT_CR
: case BT_LF
:
1504 /* This case ensures that the first attribute name is counted
1505 Apart from that we could just change state on the quote. */
1506 if (state
== inName
)
1508 else if (state
== inValue
&& nAtts
< attsMax
)
1509 atts
[nAtts
].normalized
= 0;
1513 if (state
!= inValue
)
1523 static int PTRFASTCALL
1524 PREFIX(charRefNumber
)(const ENCODING
*enc
, const char *ptr
)
1528 ptr
+= 2*MINBPC(enc
);
1529 if (CHAR_MATCHES(enc
, ptr
, ASCII_x
)) {
1530 for (ptr
+= MINBPC(enc
);
1531 !CHAR_MATCHES(enc
, ptr
, ASCII_SEMI
);
1532 ptr
+= MINBPC(enc
)) {
1533 int c
= BYTE_TO_ASCII(enc
, ptr
);
1535 case ASCII_0
: case ASCII_1
: case ASCII_2
: case ASCII_3
: case ASCII_4
:
1536 case ASCII_5
: case ASCII_6
: case ASCII_7
: case ASCII_8
: case ASCII_9
:
1538 result
|= (c
- ASCII_0
);
1540 case ASCII_A
: case ASCII_B
: case ASCII_C
:
1541 case ASCII_D
: case ASCII_E
: case ASCII_F
:
1543 result
+= 10 + (c
- ASCII_A
);
1545 case ASCII_a
: case ASCII_b
: case ASCII_c
:
1546 case ASCII_d
: case ASCII_e
: case ASCII_f
:
1548 result
+= 10 + (c
- ASCII_a
);
1551 if (result
>= 0x110000)
1556 for (; !CHAR_MATCHES(enc
, ptr
, ASCII_SEMI
); ptr
+= MINBPC(enc
)) {
1557 int c
= BYTE_TO_ASCII(enc
, ptr
);
1559 result
+= (c
- ASCII_0
);
1560 if (result
>= 0x110000)
1564 return checkCharRefNumber(result
);
1568 PREFIX(predefinedEntityName
)(const ENCODING
*enc
, const char *ptr
,
1571 switch ((end
- ptr
)/MINBPC(enc
)) {
1573 if (CHAR_MATCHES(enc
, ptr
+ MINBPC(enc
), ASCII_t
)) {
1574 switch (BYTE_TO_ASCII(enc
, ptr
)) {
1583 if (CHAR_MATCHES(enc
, ptr
, ASCII_a
)) {
1585 if (CHAR_MATCHES(enc
, ptr
, ASCII_m
)) {
1587 if (CHAR_MATCHES(enc
, ptr
, ASCII_p
))
1593 switch (BYTE_TO_ASCII(enc
, ptr
)) {
1596 if (CHAR_MATCHES(enc
, ptr
, ASCII_u
)) {
1598 if (CHAR_MATCHES(enc
, ptr
, ASCII_o
)) {
1600 if (CHAR_MATCHES(enc
, ptr
, ASCII_t
))
1607 if (CHAR_MATCHES(enc
, ptr
, ASCII_p
)) {
1609 if (CHAR_MATCHES(enc
, ptr
, ASCII_o
)) {
1611 if (CHAR_MATCHES(enc
, ptr
, ASCII_s
))
1622 PREFIX(sameName
)(const ENCODING
*enc
, const char *ptr1
, const char *ptr2
)
1625 switch (BYTE_TYPE(enc
, ptr1
)) {
1626 #define LEAD_CASE(n) \
1627 case BT_LEAD ## n: \
1628 if (*ptr1++ != *ptr2++) \
1630 LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
1633 if (*ptr1
++ != *ptr2
++)
1645 if (*ptr2
++ != *ptr1
++)
1647 if (MINBPC(enc
) > 1) {
1648 if (*ptr2
++ != *ptr1
++)
1650 if (MINBPC(enc
) > 2) {
1651 if (*ptr2
++ != *ptr1
++)
1653 if (MINBPC(enc
) > 3) {
1654 if (*ptr2
++ != *ptr1
++)
1661 if (MINBPC(enc
) == 1 && *ptr1
== *ptr2
)
1663 switch (BYTE_TYPE(enc
, ptr2
)) {
1686 PREFIX(nameMatchesAscii
)(const ENCODING
*enc
, const char *ptr1
,
1687 const char *end1
, const char *ptr2
)
1689 for (; *ptr2
; ptr1
+= MINBPC(enc
), ptr2
++) {
1692 if (!CHAR_MATCHES(enc
, ptr1
, *ptr2
))
1695 return ptr1
== end1
;
1698 static int PTRFASTCALL
1699 PREFIX(nameLength
)(const ENCODING
*enc
, const char *ptr
)
1701 const char *start
= ptr
;
1703 switch (BYTE_TYPE(enc
, ptr
)) {
1704 #define LEAD_CASE(n) \
1705 case BT_LEAD ## n: ptr += n; break;
1706 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
1720 return (int)(ptr
- start
);
1725 static const char * PTRFASTCALL
1726 PREFIX(skipS
)(const ENCODING
*enc
, const char *ptr
)
1729 switch (BYTE_TYPE(enc
, ptr
)) {
1742 PREFIX(updatePosition
)(const ENCODING
*enc
,
1747 while (ptr
!= end
) {
1748 switch (BYTE_TYPE(enc
, ptr
)) {
1749 #define LEAD_CASE(n) \
1750 case BT_LEAD ## n: \
1753 LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
1756 pos
->columnNumber
= (XML_Size
)-1;
1763 if (ptr
!= end
&& BYTE_TYPE(enc
, ptr
) == BT_LF
)
1765 pos
->columnNumber
= (XML_Size
)-1;
1771 pos
->columnNumber
++;
1776 #undef MULTIBYTE_CASES
1777 #undef INVALID_CASES
1778 #undef CHECK_NAME_CASE
1779 #undef CHECK_NAME_CASES
1780 #undef CHECK_NMSTRT_CASE
1781 #undef CHECK_NMSTRT_CASES
1783 #endif /* XML_TOK_IMPL_C */