1#![allow(missing_docs)]
32#![allow(non_snake_case)]
33#![allow(non_camel_case_types)]
34#![allow(non_upper_case_globals)]
35#![allow(unused_variables)]
36#![allow(private_interfaces)]
37#![allow(clippy::missing_safety_doc)]
38#![allow(clippy::not_unsafe_ptr_arg_deref)]
39#![allow(clippy::too_many_arguments)]
40#![allow(dead_code)]
41#![allow(unused_assignments)]
42
43use core::ffi::c_void;
44use core::ptr;
45use std::mem::size_of;
46use std::os::raw::{c_char, c_int, c_uint, c_ulong};
47
48use crate::abi::allocator::{xmlFreeImpl, xmlMallocImpl, xmlMallocZero, xmlReallocImpl};
49use crate::abi::callbacks::_xmlSAXLocator;
50use crate::abi::data_globals::{
51 xmlGenericError, xmlGenericErrorContext, xmlParserInputBufferCreateFilenameValue,
52};
53use crate::abi::structs::*;
54use crate::abi::types::*;
55use crate::xml::dtd::{create_content_model, create_int_subset, free_content_model};
56use crate::xml::parser::helpers::{
57 create_parser_ctxt, free_parser_ctxt, input_from_file, input_from_memory, setup_parser_input,
58};
59use crate::xml::sax::dispatch::SaxDispatcher;
60use crate::xml::validation::{is_xml_name_char, is_xml_name_start};
61
62const XML_PARSER_EOF_STATE: c_int = 9; const XML_PARSER_BUFFER_SIZE: usize = 512;
68const LINE_LEN: usize = 80;
69
70const XML_ENTITY_DECL: c_int = xmlElementType::XML_ENTITY_DECL as c_int;
74const XML_INTERNAL_GENERAL_ENTITY: c_int = xmlEntityType::XML_INTERNAL_GENERAL_ENTITY as c_int;
75const XML_EXTERNAL_GENERAL_PARSED_ENTITY: c_int =
76 xmlEntityType::XML_EXTERNAL_GENERAL_PARSED_ENTITY as c_int;
77const XML_INTERNAL_PARAMETER_ENTITY: c_int = xmlEntityType::XML_INTERNAL_PARAMETER_ENTITY as c_int;
78const XML_EXTERNAL_PARAMETER_ENTITY: c_int = xmlEntityType::XML_EXTERNAL_PARAMETER_ENTITY as c_int;
79const XML_INTERNAL_PREDEFINED_ENTITY: c_int = xmlEntityType::XML_INTERNAL_PREDEFINED_ENTITY as c_int;
80const XML_ATTRIBUTE_CDATA: c_int = xmlAttributeType::XML_ATTRIBUTE_CDATA as c_int;
81const XML_ATTRIBUTE_ID: c_int = xmlAttributeType::XML_ATTRIBUTE_ID as c_int;
82const XML_ATTRIBUTE_IDREF: c_int = xmlAttributeType::XML_ATTRIBUTE_IDREF as c_int;
83const XML_ATTRIBUTE_IDREFS: c_int = xmlAttributeType::XML_ATTRIBUTE_IDREFS as c_int;
84const XML_ATTRIBUTE_ENTITY: c_int = xmlAttributeType::XML_ATTRIBUTE_ENTITY as c_int;
85const XML_ATTRIBUTE_ENTITIES: c_int = xmlAttributeType::XML_ATTRIBUTE_ENTITIES as c_int;
86const XML_ATTRIBUTE_NMTOKEN: c_int = xmlAttributeType::XML_ATTRIBUTE_NMTOKEN as c_int;
87const XML_ATTRIBUTE_NMTOKENS: c_int = xmlAttributeType::XML_ATTRIBUTE_NMTOKENS as c_int;
88const XML_ATTRIBUTE_ENUMERATION: c_int = xmlAttributeType::XML_ATTRIBUTE_ENUMERATION as c_int;
89const XML_ATTRIBUTE_NOTATION: c_int = xmlAttributeType::XML_ATTRIBUTE_NOTATION as c_int;
90const XML_ATTRIBUTE_NONE: c_int = xmlAttributeDefault::XML_ATTRIBUTE_NONE as c_int;
91const XML_ATTRIBUTE_REQUIRED: c_int = xmlAttributeDefault::XML_ATTRIBUTE_REQUIRED as c_int;
92const XML_ATTRIBUTE_IMPLIED: c_int = xmlAttributeDefault::XML_ATTRIBUTE_IMPLIED as c_int;
93const XML_ATTRIBUTE_FIXED: c_int = xmlAttributeDefault::XML_ATTRIBUTE_FIXED as c_int;
94const XML_ELEMENT_CONTENT_PCDATA: c_int = xmlElementContentType::XML_ELEMENT_CONTENT_PCDATA as c_int;
95const XML_ELEMENT_CONTENT_ELEMENT: c_int = xmlElementContentType::XML_ELEMENT_CONTENT_ELEMENT as c_int;
96const XML_ELEMENT_CONTENT_SEQ: c_int = xmlElementContentType::XML_ELEMENT_CONTENT_SEQ as c_int;
97const XML_ELEMENT_CONTENT_OR: c_int = xmlElementContentType::XML_ELEMENT_CONTENT_OR as c_int;
98const XML_ELEMENT_CONTENT_ONCE: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_ONCE as c_int;
99const XML_ELEMENT_CONTENT_OPT: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_OPT as c_int;
100const XML_ELEMENT_CONTENT_MULT: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_MULT as c_int;
101const XML_ELEMENT_CONTENT_PLUS: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_PLUS as c_int;
102const XML_ELEMENT_TYPE_EMPTY: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_EMPTY as c_int;
103const XML_ELEMENT_TYPE_ANY: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_ANY as c_int;
104const XML_ELEMENT_TYPE_MIXED: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_MIXED as c_int;
105const XML_ELEMENT_TYPE_ELEMENT: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_ELEMENT as c_int;
106const XML_DOC_INTERNAL: c_int = xmlDocProperties::XML_DOC_INTERNAL as c_int;
107
108const XML_ERR_URI_REQUIRED: c_int = 100;
113const XML_ERR_PUBID_REQUIRED: c_int = 101;
114const XML_ERR_RESERVED_XML_NAME: c_int = 102;
115const XML_ERR_HYPHEN_IN_COMMENT: c_int = 103;
116const XML_ERR_EQUAL_REQUIRED: c_int = 104;
117const XML_ERR_SEPARATOR_REQUIRED: c_int = 105;
118const XML_ERR_INT_SUBSET_NOT_FINISHED: c_int = 106;
119const XML_ERR_UNKNOWN_VERSION: c_int = 107;
120const XML_ERR_ENCODING_NAME: c_int = 108;
121const XML_IO_UNKNOWN: c_int = 109;
122const XML_ERR_PCDATA_REQUIRED: c_int = 110;
123const XML_ERR_RESOURCE_LIMIT: c_int = 111;
124const XML_ERR_LTSLASH_REQUIRED: c_int = 112;
125
126unsafe impl Sync for _xmlEntity {}
129
130static PREDEF_AMP_NAME: [xmlChar; 4] = *b"amp\0";
135static PREDEF_LT_NAME: [xmlChar; 3] = *b"lt\0";
136static PREDEF_GT_NAME: [xmlChar; 3] = *b"gt\0";
137static PREDEF_QUOT_NAME: [xmlChar; 5] = *b"quot\0";
138static PREDEF_APOS_NAME: [xmlChar; 5] = *b"apos\0";
139static PREDEF_AMP_CONTENT: [xmlChar; 2] = *b"&\0";
140static PREDEF_LT_CONTENT: [xmlChar; 2] = *b"<\0";
141static PREDEF_GT_CONTENT: [xmlChar; 2] = *b">\0";
142static PREDEF_QUOT_CONTENT: [xmlChar; 2] = *b"\"\0";
143static PREDEF_APOS_CONTENT: [xmlChar; 2] = *b"'\0";
144
145static PREDEFINED_ENTITIES: [_xmlEntity; 5] = [
146 _xmlEntity {
147 _private: ptr::null_mut(),
148 type_: XML_ENTITY_DECL as c_int,
149 name: PREDEF_AMP_NAME.as_ptr(),
150 children: ptr::null_mut(),
151 last: ptr::null_mut(),
152 parent: ptr::null_mut(),
153 next: ptr::null_mut(),
154 prev: ptr::null_mut(),
155 doc: ptr::null_mut(),
156 orig: ptr::null_mut(),
157 content: PREDEF_AMP_CONTENT.as_ptr() as *mut xmlChar,
158 length: 1,
159 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
160 ExternalID: ptr::null(),
161 SystemID: ptr::null(),
162 nexte: ptr::null_mut(),
163 URI: ptr::null(),
164 owner: 0,
165 flags: 0,
166 expandedSize: 0,
167 },
168 _xmlEntity {
169 _private: ptr::null_mut(),
170 type_: XML_ENTITY_DECL as c_int,
171 name: PREDEF_LT_NAME.as_ptr(),
172 children: ptr::null_mut(),
173 last: ptr::null_mut(),
174 parent: ptr::null_mut(),
175 next: ptr::null_mut(),
176 prev: ptr::null_mut(),
177 doc: ptr::null_mut(),
178 orig: ptr::null_mut(),
179 content: PREDEF_LT_CONTENT.as_ptr() as *mut xmlChar,
180 length: 1,
181 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
182 ExternalID: ptr::null(),
183 SystemID: ptr::null(),
184 nexte: ptr::null_mut(),
185 URI: ptr::null(),
186 owner: 0,
187 flags: 0,
188 expandedSize: 0,
189 },
190 _xmlEntity {
191 _private: ptr::null_mut(),
192 type_: XML_ENTITY_DECL as c_int,
193 name: PREDEF_GT_NAME.as_ptr(),
194 children: ptr::null_mut(),
195 last: ptr::null_mut(),
196 parent: ptr::null_mut(),
197 next: ptr::null_mut(),
198 prev: ptr::null_mut(),
199 doc: ptr::null_mut(),
200 orig: ptr::null_mut(),
201 content: PREDEF_GT_CONTENT.as_ptr() as *mut xmlChar,
202 length: 1,
203 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
204 ExternalID: ptr::null(),
205 SystemID: ptr::null(),
206 nexte: ptr::null_mut(),
207 URI: ptr::null(),
208 owner: 0,
209 flags: 0,
210 expandedSize: 0,
211 },
212 _xmlEntity {
213 _private: ptr::null_mut(),
214 type_: XML_ENTITY_DECL as c_int,
215 name: PREDEF_QUOT_NAME.as_ptr(),
216 children: ptr::null_mut(),
217 last: ptr::null_mut(),
218 parent: ptr::null_mut(),
219 next: ptr::null_mut(),
220 prev: ptr::null_mut(),
221 doc: ptr::null_mut(),
222 orig: ptr::null_mut(),
223 content: PREDEF_QUOT_CONTENT.as_ptr() as *mut xmlChar,
224 length: 1,
225 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
226 ExternalID: ptr::null(),
227 SystemID: ptr::null(),
228 nexte: ptr::null_mut(),
229 URI: ptr::null(),
230 owner: 0,
231 flags: 0,
232 expandedSize: 0,
233 },
234 _xmlEntity {
235 _private: ptr::null_mut(),
236 type_: XML_ENTITY_DECL as c_int,
237 name: PREDEF_APOS_NAME.as_ptr(),
238 children: ptr::null_mut(),
239 last: ptr::null_mut(),
240 parent: ptr::null_mut(),
241 next: ptr::null_mut(),
242 prev: ptr::null_mut(),
243 doc: ptr::null_mut(),
244 orig: ptr::null_mut(),
245 content: PREDEF_APOS_CONTENT.as_ptr() as *mut xmlChar,
246 length: 1,
247 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
248 ExternalID: ptr::null(),
249 SystemID: ptr::null(),
250 nexte: ptr::null_mut(),
251 URI: ptr::null(),
252 owner: 0,
253 flags: 0,
254 expandedSize: 0,
255 },
256];
257
258#[inline]
263fn pi_is_blank_ch(c: u8) -> bool {
264 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r'
265}
266
267#[inline]
268fn pi_is_byte_char(c: u8) -> bool {
269 c == 0x09 || c == 0x0A || c == 0x0D || (0x20..=0x7E).contains(&c) || (0xA0..=0xFF).contains(&c)
270}
271
272#[inline]
273fn pi_is_pubidchar(c: u8) -> bool {
274 c == 0x20
275 || c == 0x0D
276 || c == 0x0A
277 || c.is_ascii_alphanumeric()
278 || matches!(
279 c,
280 b'-' | b'\'' | b'(' | b')' | b'+' | b',' | b'.' | b'/' | b':' | b'=' | b'?' | b';'
281 | b'!' | b'*' | b'#' | b'@' | b'$' | b'_' | b'%'
282 )
283}
284
285#[inline]
287fn pi_is_char(c: c_int) -> bool {
288 matches!(c, 0x9 | 0xA | 0xD | 0x20..=0xD7FF | 0xE000..=0xFFFD | 0x10000..=0x10FFFF)
289}
290
291#[inline]
293fn pi_is_letter_ch(c: u8) -> bool {
294 c.is_ascii_alphabetic()
295}
296
297#[inline]
299fn pi_is_digit_ch(c: u8) -> bool {
300 c.is_ascii_digit()
301}
302
303fn pi_is_name_start_char(c: c_int) -> bool {
305 if c < 0x80 {
306 return (c as u8).is_ascii_alphabetic() || c == b'_' as c_int || c == b':' as c_int;
307 }
308 if c > 0x10FFFF {
309 return false;
310 }
311 match char::from_u32(c as u32) {
312 Some(ch) => is_xml_name_start(ch),
313 None => false,
314 }
315}
316
317fn pi_is_name_char(c: c_int) -> bool {
319 if c < 0x80 {
320 let b = c as u8;
321 return b.is_ascii_alphanumeric() || b == b'_' || b == b'-' || b == b'.' || b == b':';
322 }
323 if c > 0x10FFFF {
324 return false;
325 }
326 match char::from_u32(c as u32) {
327 Some(ch) => is_xml_name_char(ch),
328 None => false,
329 }
330}
331
332#[inline]
338unsafe fn pi_input(ctxt: *mut _xmlParserCtxt) -> *mut _xmlParserInput {
339 if ctxt.is_null() {
340 return ptr::null_mut();
341 }
342 unsafe { (*ctxt).input }
343}
344
345#[inline]
347unsafe fn pi_raw(ctxt: *mut _xmlParserCtxt) -> u8 {
348 let input = unsafe { pi_input(ctxt) };
349 if input.is_null() || unsafe { (*input).cur.is_null() } {
350 return 0;
351 }
352 unsafe { *(*input).cur }
353}
354
355#[inline]
357unsafe fn pi_nxt(ctxt: *mut _xmlParserCtxt, off: isize) -> u8 {
358 let input = unsafe { pi_input(ctxt) };
359 if input.is_null() || unsafe { (*input).cur.is_null() } {
360 return 0;
361 }
362 let cur = unsafe { (*input).cur };
363 let end = unsafe { (*input).end };
364 if off >= 0 {
365 if cur.offset(off) >= end {
366 return 0;
367 }
368 unsafe { *cur.offset(off) }
369 } else {
370 let base = unsafe { (*input).base };
372 if cur.offset(off) < base {
373 return 0;
374 }
375 unsafe { *cur.offset(off) }
376 }
377}
378
379#[inline]
381unsafe fn pi_cur_ptr(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
382 let input = unsafe { pi_input(ctxt) };
383 if input.is_null() {
384 return ptr::null();
385 }
386 unsafe { (*input).cur }
387}
388
389#[inline]
391unsafe fn pi_base_ptr(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
392 let input = unsafe { pi_input(ctxt) };
393 if input.is_null() {
394 return ptr::null();
395 }
396 unsafe { (*input).base }
397}
398
399unsafe fn pi_skip(ctxt: *mut _xmlParserCtxt, val: isize) {
401 let input = unsafe { pi_input(ctxt) };
402 if input.is_null() {
403 return;
404 }
405 unsafe {
406 let cur = (*input).cur;
407 let end = (*input).end;
408 let mut n = val;
409 while n > 0 && cur.offset(n) > end {
410 n -= 1;
411 }
412 (*input).col += val as c_int;
413 (*input).cur = cur.offset(val).min(end);
414 }
415}
416
417unsafe fn pi_next1(ctxt: *mut _xmlParserCtxt) {
419 let input = unsafe { pi_input(ctxt) };
420 if input.is_null() {
421 return;
422 }
423 unsafe {
424 if (*input).cur < (*input).end {
425 (*input).cur = (*input).cur.add(1);
426 (*input).col += 1;
427 }
428 }
429}
430
431unsafe fn pi_nextl(ctxt: *mut _xmlParserCtxt, l: usize) {
433 let input = unsafe { pi_input(ctxt) };
434 if input.is_null() {
435 return;
436 }
437 unsafe {
438 let cur = (*input).cur;
439 if cur < (*input).end {
440 if *cur == b'\n' {
441 (*input).line += 1;
442 (*input).col = 1;
443 } else {
444 (*input).col += 1;
445 }
446 (*input).cur = cur.add(l).min((*input).end);
447 }
448 }
449}
450
451unsafe fn pi_next_char(ctxt: *mut _xmlParserCtxt) {
453 let input = unsafe { pi_input(ctxt) };
454 if input.is_null() {
455 return;
456 }
457 unsafe {
458 let cur = (*input).cur;
459 if cur >= (*input).end {
460 return;
461 }
462 let c = *cur;
463 if c < 0x80 {
464 if c == b'\n' {
465 (*input).cur = cur.add(1);
466 (*input).line += 1;
467 (*input).col = 1;
468 } else if c == b'\r' {
469 if cur.add(1) < (*input).end && *cur.add(1) == b'\n' {
470 (*input).cur = cur.add(2);
471 } else {
472 (*input).cur = cur.add(1);
473 }
474 (*input).line += 1;
475 (*input).col = 1;
476 } else {
477 (*input).cur = cur.add(1);
478 (*input).col += 1;
479 }
480 } else {
481 (*input).col += 1;
482 let (_, l) = pi_decode_utf8(cur, (*input).end);
483 if l == 0 {
484 (*input).cur = cur.add(1);
485 } else {
486 (*input).cur = cur.add(l);
487 }
488 }
489 }
490}
491
492unsafe fn pi_decode_utf8(ptr: *const u8, end: *const u8) -> (c_int, usize) {
497 unsafe {
498 if ptr >= end {
499 return (0, 0);
500 }
501 let c = *ptr;
502 if c < 0x80 {
503 return (c as c_int, 1);
504 }
505 let avail = end.offset_from(ptr) as usize;
506 if (0xC2..=0xDF).contains(&c) && avail >= 2 && (*ptr.add(1) & 0xC0) == 0x80 {
507 let v = (((c as c_int) & 0x1F) << 6) | ((*ptr.add(1) as c_int) & 0x3F);
508 return (v, 2);
509 }
510 if c >= 0xE0
511 && avail >= 3
512 && (*ptr.add(1) & 0xC0) == 0x80
513 && (*ptr.add(2) & 0xC0) == 0x80
514 {
515 let v = (((c as c_int) & 0x0F) << 12)
516 | (((*ptr.add(1) as c_int) & 0x3F) << 6)
517 | ((*ptr.add(2) as c_int) & 0x3F);
518 if v >= 0x800 && !(0xD800..=0xDFFF).contains(&v) {
519 return (v, 3);
520 }
521 return (0xFFFD, 1);
522 }
523 if c >= 0xF0
524 && avail >= 4
525 && (*ptr.add(1) & 0xC0) == 0x80
526 && (*ptr.add(2) & 0xC0) == 0x80
527 && (*ptr.add(3) & 0xC0) == 0x80
528 {
529 let v = (((c as c_int) & 0x07) << 18)
530 | (((*ptr.add(1) as c_int) & 0x3F) << 12)
531 | (((*ptr.add(2) as c_int) & 0x3F) << 6)
532 | ((*ptr.add(3) as c_int) & 0x3F);
533 if (0x10000..=0x10FFFF).contains(&v) {
534 return (v, 4);
535 }
536 return (0xFFFD, 1);
537 }
538 (0xFFFD, 1)
539 }
540}
541
542unsafe fn pi_current_char(ctxt: *mut _xmlParserCtxt) -> (c_int, usize) {
544 let input = unsafe { pi_input(ctxt) };
545 if input.is_null() || unsafe { (*input).cur.is_null() } {
546 return (0, 0);
547 }
548 unsafe {
549 let cur = (*input).cur;
550 if cur >= (*input).end {
551 return (0, 0);
552 }
553 pi_decode_utf8(cur, (*input).end)
554 }
555}
556
557unsafe fn pi_current_char_recover(ctxt: *mut _xmlParserCtxt) -> (c_int, usize) {
559 let (c, l) = unsafe { pi_current_char(ctxt) };
560 if c == 0 {
561 (0xFFFD, 1)
562 } else {
563 (c, l)
564 }
565}
566
567#[inline]
569unsafe fn pi_stopped(ctxt: *mut _xmlParserCtxt) -> bool {
570 unsafe { (*ctxt).errNo != XML_ERR_OK || (*ctxt).disableSAX != 0 }
571}
572
573unsafe fn pi_fatal_err(ctxt: *mut _xmlParserCtxt, code: c_int) {
575 unsafe {
576 let c = &mut *ctxt;
577 if c.errNo == XML_ERR_OK {
578 c.errNo = code;
579 }
580 c.wellFormed = 0;
581 }
582}
583
584unsafe fn pi_err_memory(ctxt: *mut _xmlParserCtxt) {
586 unsafe {
587 let c = &mut *ctxt;
588 if c.errNo == XML_ERR_OK {
589 c.errNo = XML_ERR_NO_MEMORY;
590 }
591 c.wellFormed = 0;
592 }
593}
594
595unsafe fn pi_strndup_bytes(start: *const xmlChar, len: usize) -> *mut xmlChar {
597 unsafe {
598 let buf = xmlMallocImpl(len + 1) as *mut xmlChar;
599 if buf.is_null() {
600 return ptr::null_mut();
601 }
602 ptr::copy_nonoverlapping(start, buf, len);
603 *buf.add(len) = 0;
604 buf
605 }
606}
607
608fn pi_push_codepoint(buf: &mut Vec<u8>, c: c_int) {
610 if c < 0x80 {
611 buf.push(c as u8);
612 } else if c < 0x800 {
613 buf.push((0xC0 | ((c >> 6) & 0x1F)) as u8);
614 buf.push((0x80 | (c & 0x3F)) as u8);
615 } else if c < 0x10000 {
616 buf.push((0xE0 | ((c >> 12) & 0x0F)) as u8);
617 buf.push((0x80 | ((c >> 6) & 0x3F)) as u8);
618 buf.push((0x80 | (c & 0x3F)) as u8);
619 } else {
620 buf.push((0xF0 | ((c >> 18) & 0x07)) as u8);
621 buf.push((0x80 | ((c >> 12) & 0x3F)) as u8);
622 buf.push((0x80 | ((c >> 6) & 0x3F)) as u8);
623 buf.push((0x80 | (c & 0x3F)) as u8);
624 }
625}
626
627unsafe fn pi_skip_blanks(ctxt: *mut _xmlParserCtxt) -> c_int {
630 let mut res: c_int = 0;
631 unsafe {
632 loop {
633 if pi_stopped(ctxt) {
634 break;
635 }
636 let input = pi_input(ctxt);
637 if input.is_null() {
638 break;
639 }
640 if (*input).cur >= (*input).end || *(*input).cur == 0 {
641 if (*input).entity.is_null() || (*ctxt).inputNr <= 1 {
644 break;
645 }
646 pi_pop_pe(ctxt);
647 res = res.saturating_add(1);
648 continue;
649 }
650 let c = *(*input).cur;
651 if pi_is_blank_ch(c) {
652 pi_next_char(ctxt);
653 res = res.saturating_add(1);
654 } else {
655 break;
656 }
657 }
658 }
659 res
660}
661
662#[inline]
664unsafe fn pi_cmp6(ctxt: *mut _xmlParserCtxt, s: &[u8; 6]) -> bool {
665 unsafe { pi_nxt(ctxt, 0) == s[0] && pi_nxt(ctxt, 1) == s[1] && pi_nxt(ctxt, 2) == s[2] && pi_nxt(ctxt, 3) == s[3] && pi_nxt(ctxt, 4) == s[4] && pi_nxt(ctxt, 5) == s[5] }
666}
667
668#[inline]
669unsafe fn pi_cmp5(ctxt: *mut _xmlParserCtxt, s: &[u8; 5]) -> bool {
670 unsafe { pi_nxt(ctxt, 0) == s[0] && pi_nxt(ctxt, 1) == s[1] && pi_nxt(ctxt, 2) == s[2] && pi_nxt(ctxt, 3) == s[3] && pi_nxt(ctxt, 4) == s[4] }
671}
672
673#[inline]
674unsafe fn pi_cmp7(ctxt: *mut _xmlParserCtxt, s: &[u8; 7]) -> bool {
675 unsafe {
676 pi_cmp6(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5]]) && pi_nxt(ctxt, 6) == s[6]
677 }
678}
679
680#[inline]
681unsafe fn pi_cmp8(ctxt: *mut _xmlParserCtxt, s: &[u8; 8]) -> bool {
682 unsafe {
683 pi_cmp7(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5], s[6]])
684 && pi_nxt(ctxt, 7) == s[7]
685 }
686}
687
688#[inline]
689unsafe fn pi_cmp9(ctxt: *mut _xmlParserCtxt, s: &[u8; 9]) -> bool {
690 unsafe {
691 pi_cmp8(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]])
692 && pi_nxt(ctxt, 8) == s[8]
693 }
694}
695
696#[inline]
697unsafe fn pi_cmp10(ctxt: *mut _xmlParserCtxt, s: &[u8; 10]) -> bool {
698 unsafe {
699 pi_cmp9(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8]])
700 && pi_nxt(ctxt, 9) == s[9]
701 }
702}
703
704unsafe fn pi_name_push(ctxt: *mut _xmlParserCtxt, name: *const xmlChar) -> c_int {
710 unsafe {
711 let c = &mut *ctxt;
712 if c.nameNr >= c.nameMax {
713 let new_max = if c.nameMax == 0 { 10 } else { c.nameMax * 2 };
714 let new_tab = xmlReallocImpl(
715 c.nameTab as *mut c_void,
716 (new_max as usize) * size_of::<*const xmlChar>(),
717 ) as *mut *const xmlChar;
718 if new_tab.is_null() {
719 return -1;
720 }
721 c.nameTab = new_tab;
722 c.nameMax = new_max;
723 }
724 *c.nameTab.add(c.nameNr as usize) = name;
725 c.nameNr += 1;
726 c.name = name;
727 }
728 0
729}
730
731unsafe fn pi_name_pop(ctxt: *mut _xmlParserCtxt) {
733 unsafe {
734 let c = &mut *ctxt;
735 if c.nameNr <= 0 {
736 return;
737 }
738 c.nameNr -= 1;
739 let old = *c.nameTab.add(c.nameNr as usize);
740 *c.nameTab.add(c.nameNr as usize) = ptr::null();
741 if c.nameNr == 0 {
742 c.name = ptr::null();
743 } else {
744 c.name = *c.nameTab.add((c.nameNr - 1) as usize);
745 }
746 if !old.is_null() {
747 xmlFreeImpl(old as *mut c_void);
748 }
749 }
750}
751
752unsafe fn pi_space_push(ctxt: *mut _xmlParserCtxt, val: c_int) -> c_int {
754 unsafe {
755 let c = &mut *ctxt;
756 if c.spaceNr >= c.spaceMax {
757 let new_max = if c.spaceMax == 0 { 10 } else { c.spaceMax * 2 };
758 let new_tab = xmlReallocImpl(
759 c.spaceTab as *mut c_void,
760 (new_max as usize) * size_of::<c_int>(),
761 ) as *mut c_int;
762 if new_tab.is_null() {
763 return -1;
764 }
765 c.spaceTab = new_tab;
766 c.spaceMax = new_max;
767 }
768 *c.spaceTab.add(c.spaceNr as usize) = val;
769 c.spaceNr += 1;
770 c.space = c.spaceTab.add((c.spaceNr - 1) as usize);
771 }
772 0
773}
774
775unsafe fn pi_space_pop(ctxt: *mut _xmlParserCtxt) {
777 unsafe {
778 let c = &mut *ctxt;
779 if c.spaceNr <= 0 {
780 return;
781 }
782 c.spaceNr -= 1;
783 if c.spaceNr == 0 {
784 c.space = ptr::null_mut();
785 } else {
786 c.space = c.spaceTab.add((c.spaceNr - 1) as usize);
787 }
788 }
789}
790
791unsafe fn pi_node_push(ctxt: *mut _xmlParserCtxt, node: *mut _xmlNode) -> c_int {
793 unsafe {
794 let c = &mut *ctxt;
795 if c.nodeNr >= c.nodeMax {
796 let new_max = if c.nodeMax == 0 { 10 } else { c.nodeMax * 2 };
797 let new_tab = xmlReallocImpl(
798 c.nodeTab as *mut c_void,
799 (new_max as usize) * size_of::<*mut _xmlNode>(),
800 ) as *mut *mut _xmlNode;
801 if new_tab.is_null() {
802 return -1;
803 }
804 c.nodeTab = new_tab;
805 c.nodeMax = new_max;
806 }
807 *c.nodeTab.add(c.nodeNr as usize) = node;
808 c.nodeNr += 1;
809 c.node = node;
810 }
811 0
812}
813
814unsafe fn pi_node_pop(ctxt: *mut _xmlParserCtxt) {
816 unsafe {
817 let c = &mut *ctxt;
818 if c.nodeNr <= 0 {
819 return;
820 }
821 c.nodeNr -= 1;
822 if c.nodeNr == 0 {
823 c.node = ptr::null_mut();
824 } else {
825 c.node = *c.nodeTab.add((c.nodeNr - 1) as usize);
826 }
827 }
828}
829
830unsafe fn pi_input_push(ctxt: *mut _xmlParserCtxt, input: *mut _xmlParserInput) -> c_int {
832 unsafe {
833 if ctxt.is_null() || input.is_null() {
834 return -1;
835 }
836 let c = &mut *ctxt;
837 if c.inputNr >= c.inputMax {
838 let new_max = if c.inputMax == 0 { 4 } else { c.inputMax * 2 };
839 let new_tab = xmlReallocImpl(
840 c.inputTab as *mut c_void,
841 (new_max as usize) * size_of::<*mut _xmlParserInput>(),
842 ) as *mut *mut _xmlParserInput;
843 if new_tab.is_null() {
844 return -1;
845 }
846 c.inputTab = new_tab;
847 c.inputMax = new_max;
848 }
849 *c.inputTab.add(c.inputNr as usize) = input;
850 c.input = input;
851 c.inputNr += 1;
852 }
853 0
854}
855
856unsafe fn pi_input_pop(ctxt: *mut _xmlParserCtxt) -> *mut _xmlParserInput {
858 unsafe {
859 if ctxt.is_null() {
860 return ptr::null_mut();
861 }
862 let c = &mut *ctxt;
863 if c.inputNr <= 0 {
864 return ptr::null_mut();
865 }
866 c.inputNr -= 1;
867 if c.inputNr > 0 {
868 c.input = *c.inputTab.add((c.inputNr - 1) as usize);
869 } else {
870 c.input = ptr::null_mut();
871 }
872 let ret = *c.inputTab.add(c.inputNr as usize);
873 *c.inputTab.add(c.inputNr as usize) = ptr::null_mut();
874 ret
875 }
876}
877
878unsafe fn pi_pop_pe(ctxt: *mut _xmlParserCtxt) {
880 unsafe {
881 let input = pi_input_pop(ctxt);
882 if input.is_null() {
883 return;
884 }
885 let base = (*input).base;
886 if !base.is_null() && !(*input).entity.is_null() {
887 xmlFreeImpl(base as *mut c_void);
888 }
889 xmlFreeImpl(input as *mut c_void);
890 }
891}
892
893unsafe fn pi_ctxt_late_init(ctxt: *mut _xmlParserCtxt) {
895 unsafe {
896 if ctxt.is_null() {
897 return;
898 }
899 let c = &mut *ctxt;
900 if !c.sax.is_null() && (*c.sax).initialized == XML_SAX2_MAGIC as c_uint {
901 c.sax2 = 1;
902 }
903 }
904}
905
906unsafe fn pi_split_qname(qname: *const xmlChar) -> (*const xmlChar, *const xmlChar) {
908 if qname.is_null() {
909 return (ptr::null(), ptr::null());
910 }
911 unsafe {
912 let mut p = qname;
913 while *p != 0 {
914 if *p == b':' {
915 return (p.add(1), qname);
916 }
917 p = p.add(1);
918 }
919 }
920 (qname, ptr::null())
921}
922
923unsafe fn pi_cstr_eq(s: *const xmlChar, bytes: &[u8]) -> bool {
925 if s.is_null() {
926 return bytes.is_empty();
927 }
928 unsafe {
929 let mut i = 0usize;
930 loop {
931 let b = *s.add(i);
932 if i >= bytes.len() {
933 return b == 0;
934 }
935 if b != bytes[i] {
936 return false;
937 }
938 i += 1;
939 }
940 }
941}
942
943unsafe fn pi_get_predefined_entity(name: *const xmlChar) -> *mut _xmlEntity {
949 if name.is_null() {
950 return ptr::null_mut();
951 }
952 for e in PREDEFINED_ENTITIES.iter() {
953 if unsafe { crate::abi::exports_xml2::xmlStrcmp(e.name, name) == 0 } {
954 return e as *const _xmlEntity as *mut _xmlEntity;
955 }
956 }
957 ptr::null_mut()
958}
959
960unsafe fn pi_lookup_general_entity(ctxt: *mut _xmlParserCtxt, name: *const xmlChar) -> *mut _xmlEntity {
963 unsafe {
964 if (*ctxt).options & XML_PARSE_OLDSAX == 0 {
966 let ent = pi_get_predefined_entity(name);
967 if !ent.is_null() {
968 return ent;
969 }
970 }
971 let c = &*ctxt;
972 if !c.sax.is_null() {
973 let ent = SaxDispatcher::get_entity(&*c.sax, c.userData, name);
974 if !ent.is_null() {
975 return ent;
976 }
977 if c.userData == ctxt as *mut c_void {
978 let ent2 = crate::abi::exports_xml2::xmlSAX2GetEntity(c.userData, name);
979 if !ent2.is_null() {
980 return ent2;
981 }
982 }
983 }
984 ptr::null_mut()
985 }
986}
987
988unsafe fn pi_lookup_parameter_entity(ctxt: *mut _xmlParserCtxt, name: *const xmlChar) -> *mut _xmlEntity {
990 unsafe {
991 let c = &*ctxt;
992 if !c.sax.is_null() {
993 let ent = SaxDispatcher::get_parameter_entity(&*c.sax, c.userData, name);
994 if !ent.is_null() {
995 return ent;
996 }
997 if c.userData == ctxt as *mut c_void {
998 let ent2 = crate::abi::exports_xml2::xmlSAX2GetParameterEntity(c.userData, name);
999 if !ent2.is_null() {
1000 return ent2;
1001 }
1002 }
1003 }
1004 ptr::null_mut()
1005 }
1006}
1007
1008unsafe fn pi_sax_chars(ctxt: *mut _xmlParserCtxt, bytes: &[u8], ignorable: bool) {
1014 if bytes.is_empty() {
1015 return;
1016 }
1017 unsafe {
1018 let c = &*ctxt;
1019 if c.sax.is_null() || c.disableSAX != 0 {
1020 return;
1021 }
1022 let buf = pi_strndup_bytes(bytes.as_ptr(), bytes.len());
1023 if buf.is_null() {
1024 return;
1025 }
1026 if ignorable {
1027 SaxDispatcher::ignorable_whitespace(&*c.sax, c.userData, buf, bytes.len() as c_int);
1028 } else {
1029 SaxDispatcher::characters(&*c.sax, c.userData, buf, bytes.len() as c_int);
1030 }
1031 xmlFreeImpl(buf as *mut c_void);
1032 }
1033}
1034
1035unsafe fn pi_sax_comment(ctxt: *mut _xmlParserCtxt, bytes: &[u8]) {
1037 unsafe {
1038 let c = &*ctxt;
1039 if c.sax.is_null() || c.disableSAX != 0 {
1040 return;
1041 }
1042 let buf = if bytes.is_empty() {
1043 ptr::null()
1044 } else {
1045 pi_strndup_bytes(bytes.as_ptr(), bytes.len())
1046 };
1047 if bytes.is_empty() || !buf.is_null() {
1048 SaxDispatcher::comment(&*c.sax, c.userData, buf);
1049 }
1050 if !buf.is_null() {
1051 xmlFreeImpl(buf as *mut c_void);
1052 }
1053 }
1054}
1055
1056unsafe fn pi_sax_pi(ctxt: *mut _xmlParserCtxt, target: *const xmlChar, data: &[u8]) {
1058 unsafe {
1059 let c = &*ctxt;
1060 if c.sax.is_null() || c.disableSAX != 0 {
1061 return;
1062 }
1063 let buf = if data.is_empty() {
1064 ptr::null()
1065 } else {
1066 pi_strndup_bytes(data.as_ptr(), data.len())
1067 };
1068 if data.is_empty() || !buf.is_null() {
1069 SaxDispatcher::processing_instruction(&*c.sax, c.userData, target, buf);
1070 }
1071 if !buf.is_null() {
1072 xmlFreeImpl(buf as *mut c_void);
1073 }
1074 }
1075}
1076
1077unsafe fn pi_dispatch_start_element(
1084 ctxt: *mut _xmlParserCtxt,
1085 qname: *const xmlChar,
1086 atts: *mut *const xmlChar,
1087 nbatts: usize,
1088) {
1089 unsafe {
1090 let c = &*ctxt;
1091 if c.sax.is_null() || c.disableSAX != 0 {
1092 return;
1093 }
1094 let sax = &*c.sax;
1095 let (local, prefix) = pi_split_qname(qname);
1096 if let Some(cb2) = sax.startElementNs {
1097 let nattr = nbatts / 2;
1098 let mut namespaces: Vec<*const xmlChar> = Vec::new();
1099 let mut attrs2: Vec<*const xmlChar> = Vec::new();
1100 for k in 0..nattr {
1101 let aname = *atts.add(k * 2);
1102 let aval = *atts.add(k * 2 + 1);
1103 if aname.is_null() {
1104 continue;
1105 }
1106 let (alocal, apref) = pi_split_qname(aname);
1107 if apref.is_null() && pi_cstr_eq(aname, b"xmlns") {
1108 namespaces.push(ptr::null());
1109 namespaces.push(aval);
1110 } else if !apref.is_null() && pi_cstr_eq(apref, b"xmlns") {
1111 namespaces.push(alocal);
1112 namespaces.push(aval);
1113 } else {
1114 attrs2.push(alocal);
1115 attrs2.push(apref);
1116 attrs2.push(ptr::null());
1117 attrs2.push(aval);
1118 attrs2.push(aval.add(crate::abi::exports_xml2::xmlStrlen(aval) as usize));
1119 }
1120 }
1121 cb2(
1122 c.userData,
1123 local,
1124 prefix,
1125 ptr::null(),
1126 (namespaces.len() / 2) as c_int,
1127 namespaces.as_mut_ptr(),
1128 (attrs2.len() / 5) as c_int,
1129 0,
1130 attrs2.as_mut_ptr(),
1131 );
1132 } else if let Some(cb1) = sax.startElement {
1133 let sa1 = if nbatts > 0 {
1134 let mut arr: Vec<*const xmlChar> = Vec::with_capacity(nbatts + 2);
1136 for i in 0..nbatts {
1137 arr.push(*atts.add(i));
1138 }
1139 arr.push(ptr::null());
1140 arr.push(ptr::null());
1141 arr.as_mut_ptr()
1142 } else {
1143 ptr::null_mut()
1144 };
1145 cb1(c.userData, qname, sa1);
1146 }
1147 }
1148}
1149
1150unsafe fn pi_dispatch_end_element(ctxt: *mut _xmlParserCtxt, qname: *const xmlChar) {
1152 unsafe {
1153 let c = &*ctxt;
1154 if c.sax.is_null() || c.disableSAX != 0 {
1155 return;
1156 }
1157 let sax = &*c.sax;
1158 let (local, prefix) = pi_split_qname(qname);
1159 if let Some(cb2) = sax.endElementNs {
1160 cb2(c.userData, local, prefix, ptr::null());
1161 } else if let Some(cb1) = sax.endElement {
1162 cb1(c.userData, qname);
1163 }
1164 }
1165}
1166
1167unsafe fn pi_parse_name(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
1174 unsafe {
1175 let input = pi_input(ctxt);
1176 if input.is_null() || (*input).cur.is_null() {
1177 return ptr::null();
1178 }
1179 let in_ptr = (*input).cur;
1180 let end = (*input).end;
1181 let first = *in_ptr;
1182
1183 if (first.is_ascii_lowercase() || first.is_ascii_uppercase() || first == b'_' || first == b':')
1185 && in_ptr < end
1186 {
1187 let mut p = in_ptr.add(1);
1188 while p < end {
1189 let b = *p;
1190 if b.is_ascii_alphanumeric() || b == b'_' || b == b'-' || b == b':' || b == b'.' {
1191 p = p.add(1);
1192 } else {
1193 break;
1194 }
1195 }
1196 if p >= end || (*p > 0 && *p < 0x80) {
1197 let count = p.offset_from(in_ptr) as usize;
1198 if count > 0 {
1199 let ret = pi_strndup_bytes(in_ptr, count);
1200 if ret.is_null() {
1201 pi_err_memory(ctxt);
1202 return ptr::null();
1203 }
1204 (*input).cur = p;
1205 (*input).col += count as c_int;
1206 return ret;
1207 }
1208 }
1209 }
1210
1211 let start = (*input).cur;
1213 let (c, l) = pi_current_char(ctxt);
1214 if !pi_is_name_start_char(c) {
1215 return ptr::null();
1216 }
1217 let mut len = l;
1218 pi_nextl(ctxt, l);
1219 loop {
1220 let (c2, l2) = pi_current_char(ctxt);
1221 if !pi_is_name_char(c2) {
1222 break;
1223 }
1224 len += l2;
1225 pi_nextl(ctxt, l2);
1226 }
1227 let ret = pi_strndup_bytes(start, len);
1228 if ret.is_null() {
1229 pi_err_memory(ctxt);
1230 }
1231 ret
1232 }
1233}
1234
1235unsafe fn pi_parse_nmtoken(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1237 unsafe {
1238 let mut buf: Vec<u8> = Vec::new();
1239 loop {
1240 let (c, l) = pi_current_char(ctxt);
1241 if !pi_is_name_char(c) {
1242 break;
1243 }
1244 pi_push_codepoint(&mut buf, c);
1245 pi_nextl(ctxt, l);
1246 }
1247 if buf.is_empty() {
1248 return ptr::null_mut();
1249 }
1250 let ret = pi_strndup_bytes(buf.as_ptr(), buf.len());
1251 if ret.is_null() {
1252 pi_err_memory(ctxt);
1253 }
1254 ret
1255 }
1256}
1257
1258unsafe fn pi_parse_name_and_compare(ctxt: *mut _xmlParserCtxt, other: *const xmlChar) -> *const xmlChar {
1260 unsafe {
1261 let input = pi_input(ctxt);
1262 if input.is_null() || other.is_null() {
1263 return ptr::null();
1264 }
1265 let mut in_ptr = (*input).cur;
1266 let mut cmp = other;
1267 while !in_ptr.is_null() && *in_ptr != 0 && *in_ptr == *cmp {
1268 in_ptr = in_ptr.add(1);
1269 cmp = cmp.add(1);
1270 }
1271 if *cmp == 0 && (*in_ptr == b'>' || pi_is_blank_ch(*in_ptr)) {
1272 (*input).col += in_ptr.offset_from((*input).cur) as c_int;
1273 (*input).cur = in_ptr;
1274 return 1 as *const xmlChar;
1275 }
1276 let ret = pi_parse_name(ctxt);
1277 if !ret.is_null() && crate::abi::exports_xml2::xmlStrcmp(ret, other) == 0 {
1278 xmlFreeImpl(ret as *mut c_void);
1279 return 1 as *const xmlChar;
1280 }
1281 ret
1282 }
1283}
1284
1285unsafe fn pi_parse_char_ref(ctxt: *mut _xmlParserCtxt) -> c_int {
1287 unsafe {
1288 let mut val: c_int = 0;
1289 let mut count: c_int = 0;
1290 if pi_raw(ctxt) == b'&' && pi_nxt(ctxt, 1) == b'#' && pi_nxt(ctxt, 2) == b'x' {
1291 pi_skip(ctxt, 3);
1292 while pi_raw(ctxt) != b';' && !pi_stopped(ctxt) {
1293 if count > 20 {
1294 count = 0;
1295 }
1296 let c = pi_raw(ctxt);
1297 if c.is_ascii_digit() {
1298 val = val * 16 + (c - b'0') as c_int;
1299 } else if (b'a'..=b'f').contains(&c) {
1300 val = val * 16 + (c - b'a') as c_int + 10;
1301 } else if (b'A'..=b'F').contains(&c) {
1302 val = val * 16 + (c - b'A') as c_int + 10;
1303 } else {
1304 pi_fatal_err(ctxt, XML_ERR_INVALID_HEX_CHARREF);
1305 val = 0;
1306 break;
1307 }
1308 if val > 0x110000 {
1309 val = 0x110000;
1310 }
1311 pi_next1(ctxt);
1312 count += 1;
1313 }
1314 if pi_raw(ctxt) == b';' {
1315 pi_next1(ctxt);
1316 }
1317 } else if pi_raw(ctxt) == b'&' && pi_nxt(ctxt, 1) == b'#' {
1318 pi_skip(ctxt, 2);
1319 while pi_raw(ctxt) != b';' {
1320 if count > 20 {
1321 count = 0;
1322 }
1323 let c = pi_raw(ctxt);
1324 if c.is_ascii_digit() {
1325 val = val * 10 + (c - b'0') as c_int;
1326 } else {
1327 pi_fatal_err(ctxt, XML_ERR_INVALID_DEC_CHARREF);
1328 val = 0;
1329 break;
1330 }
1331 if val > 0x110000 {
1332 val = 0x110000;
1333 }
1334 pi_next1(ctxt);
1335 count += 1;
1336 }
1337 if pi_raw(ctxt) == b';' {
1338 pi_next1(ctxt);
1339 }
1340 } else {
1341 if pi_raw(ctxt) == b'&' {
1342 pi_skip(ctxt, 1);
1343 }
1344 pi_fatal_err(ctxt, XML_ERR_INVALID_CHARREF);
1345 }
1346
1347 if val >= 0x110000 {
1349 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1350 val = 0xFFFD;
1351 } else if !pi_is_char(val) {
1352 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1353 }
1354 val
1355 }
1356}
1357
1358unsafe fn pi_parse_entity_ref(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEntity {
1360 unsafe {
1361 if ctxt.is_null() {
1362 return ptr::null_mut();
1363 }
1364 let name = pi_parse_entity_ref_name(ctxt);
1365 if name.is_null() {
1366 return ptr::null_mut();
1367 }
1368 let ent = pi_lookup_general_entity(ctxt, name);
1369 xmlFreeImpl(name as *mut c_void);
1370 ent
1371 }
1372}
1373
1374unsafe fn pi_parse_entity_ref_name(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
1376 unsafe {
1377 if pi_raw(ctxt) != b'&' {
1378 return ptr::null();
1379 }
1380 pi_next1(ctxt);
1381 let name = pi_parse_name(ctxt);
1382 if name.is_null() {
1383 pi_fatal_err(ctxt, XML_ERR_ENTITYREF_NO_NAME);
1384 return ptr::null();
1385 }
1386 if pi_raw(ctxt) != b';' {
1387 pi_fatal_err(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING);
1388 xmlFreeImpl(name as *mut c_void);
1389 return ptr::null();
1390 }
1391 pi_next1(ctxt);
1392 name
1393 }
1394}
1395
1396unsafe fn pi_parse_entity_value(ctxt: *mut _xmlParserCtxt, orig: *mut *mut xmlChar) -> *mut xmlChar {
1398 unsafe {
1399 let quote = pi_raw(ctxt);
1400 if quote != b'"' && quote != b'\'' {
1401 pi_fatal_err(ctxt, XML_ERR_ENTITY_NOT_STARTED);
1402 return ptr::null_mut();
1403 }
1404 let start = pi_cur_ptr(ctxt);
1405 pi_next1(ctxt);
1406 let mut len: usize = 0;
1407 loop {
1408 if pi_stopped(ctxt) {
1409 return ptr::null_mut();
1410 }
1411 let input = pi_input(ctxt);
1412 if input.is_null() || (*input).cur >= (*input).end {
1413 pi_fatal_err(ctxt, XML_ERR_ENTITY_NOT_FINISHED);
1414 return ptr::null_mut();
1415 }
1416 let c = pi_raw(ctxt);
1417 if c == 0 {
1418 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1419 return ptr::null_mut();
1420 }
1421 if c == quote {
1422 break;
1423 }
1424 pi_next1(ctxt);
1425 len += 1;
1426 }
1427 if !orig.is_null() {
1428 *orig = pi_strndup_bytes(start, len);
1429 }
1430 let val = pi_strndup_bytes(start, len);
1431 pi_next1(ctxt);
1432 val
1433 }
1434}
1435
1436unsafe fn pi_parse_att_value(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1439 unsafe {
1440 if ctxt.is_null() || pi_input(ctxt).is_null() {
1441 return ptr::null_mut();
1442 }
1443 let quote = pi_raw(ctxt);
1444 if quote != b'"' && quote != b'\'' {
1445 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED);
1446 return ptr::null_mut();
1447 }
1448 pi_next1(ctxt);
1449 let replace_entities = (*ctxt).replaceEntities != 0;
1450 let mut out: Vec<u8> = Vec::new();
1451 loop {
1452 if pi_stopped(ctxt) {
1453 return ptr::null_mut();
1454 }
1455 let input = pi_input(ctxt);
1456 if input.is_null() {
1457 return ptr::null_mut();
1458 }
1459 if (*input).cur >= (*input).end {
1460 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED);
1461 return ptr::null_mut();
1462 }
1463 let c = pi_raw(ctxt);
1464 if c == quote {
1465 break;
1466 }
1467 if c >= 0x80 {
1468 let (ch, l) = pi_current_char(ctxt);
1469 if ch == 0 {
1470 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1471 return ptr::null_mut();
1472 }
1473 pi_push_codepoint(&mut out, ch);
1474 pi_nextl(ctxt, l);
1475 } else if c == b'&' {
1476 if pi_nxt(ctxt, 1) == b'#' {
1477 let val = pi_parse_char_ref(ctxt);
1478 if val == 0 {
1479 return ptr::null_mut();
1480 }
1481 if val == b'&' as c_int && !replace_entities {
1482 out.extend_from_slice(b"&");
1483 } else {
1484 pi_push_codepoint(&mut out, val);
1485 }
1486 } else {
1487 let name = pi_parse_entity_ref_name(ctxt);
1488 if name.is_null() {
1489 return ptr::null_mut();
1490 }
1491 let ent = pi_lookup_general_entity(ctxt, name);
1492 let mut expanded = false;
1493 if !ent.is_null() {
1494 let etype = (*ent).etype;
1495 let content = (*ent).content;
1496 if !content.is_null() {
1497 if etype == XML_INTERNAL_PREDEFINED_ENTITY as c_int {
1498 if *content == b'&' && !replace_entities {
1499 out.extend_from_slice(b"&");
1500 } else {
1501 let l = crate::abi::exports_xml2::xmlStrlen(content) as usize;
1502 out.extend_from_slice(core::slice::from_raw_parts(content, l));
1503 }
1504 expanded = true;
1505 } else if replace_entities
1506 && etype == XML_INTERNAL_GENERAL_ENTITY as c_int
1507 {
1508 let l = crate::abi::exports_xml2::xmlStrlen(content) as usize;
1509 out.extend_from_slice(core::slice::from_raw_parts(content, l));
1510 expanded = true;
1511 }
1512 }
1513 }
1514 if !expanded {
1515 out.push(b'&');
1516 let l = crate::abi::exports_xml2::xmlStrlen(name) as usize;
1517 out.extend_from_slice(core::slice::from_raw_parts(name, l));
1518 out.push(b';');
1519 }
1520 xmlFreeImpl(name as *mut c_void);
1521 }
1522 } else {
1523 if c == b'<' {
1524 pi_fatal_err(ctxt, XML_ERR_LT_IN_ATTRIBUTE);
1525 }
1526 if c < 0x20 {
1527 out.push(b' ');
1529 if c == b'\r' && pi_nxt(ctxt, 1) == b'\n' {
1530 pi_next1(ctxt);
1531 }
1532 } else {
1533 out.push(c);
1534 }
1535 pi_next1(ctxt);
1536 }
1537 }
1538 pi_next1(ctxt);
1539 out.push(0);
1540 let ret = pi_strndup_bytes(out.as_ptr(), out.len() - 1);
1541 ret
1542 }
1543}
1544
1545unsafe fn pi_parse_system_literal(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1547 unsafe {
1548 let stop = if pi_raw(ctxt) == b'"' {
1549 pi_next1(ctxt);
1550 b'"'
1551 } else if pi_raw(ctxt) == b'\'' {
1552 pi_next1(ctxt);
1553 b'\''
1554 } else {
1555 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_STARTED);
1556 return ptr::null_mut();
1557 };
1558 let mut buf: Vec<u8> = Vec::new();
1559 loop {
1560 let (cur, l) = pi_current_char_recover(ctxt);
1561 if !pi_is_char(cur) || cur == stop as c_int {
1562 break;
1563 }
1564 pi_push_codepoint(&mut buf, cur);
1565 pi_nextl(ctxt, l);
1566 }
1567 let cur = pi_raw(ctxt);
1568 if !pi_is_char(cur as c_int) {
1569 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_FINISHED);
1570 } else if cur == stop {
1571 pi_next1(ctxt);
1572 }
1573 pi_strndup_bytes(buf.as_ptr(), buf.len())
1574 }
1575}
1576
1577unsafe fn pi_parse_pubid_literal(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1579 unsafe {
1580 let stop = if pi_raw(ctxt) == b'"' {
1581 pi_next1(ctxt);
1582 b'"'
1583 } else if pi_raw(ctxt) == b'\'' {
1584 pi_next1(ctxt);
1585 b'\''
1586 } else {
1587 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_STARTED);
1588 return ptr::null_mut();
1589 };
1590 let mut buf: Vec<u8> = Vec::new();
1591 loop {
1592 let cur = pi_raw(ctxt);
1593 if !pi_is_pubidchar(cur) || cur == stop {
1594 break;
1595 }
1596 buf.push(cur);
1597 pi_next1(ctxt);
1598 }
1599 if pi_raw(ctxt) != stop {
1600 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_FINISHED);
1601 } else {
1602 pi_next1(ctxt);
1603 }
1604 pi_strndup_bytes(buf.as_ptr(), buf.len())
1605 }
1606}
1607
1608unsafe fn pi_parse_quoted_string(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1610 unsafe {
1611 if ctxt.is_null() || pi_input(ctxt).is_null() {
1612 return ptr::null_mut();
1613 }
1614 let ret = pi_parse_att_value(ctxt);
1615 if ret.is_null() {
1616 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
1617 }
1618 ret
1619 }
1620}
1621
1622unsafe fn pi_parse_external_id(
1624 ctxt: *mut _xmlParserCtxt,
1625 public_id: *mut *mut xmlChar,
1626 strict: c_int,
1627) -> *mut xmlChar {
1628 unsafe {
1629 *public_id = ptr::null_mut();
1630 let mut uri: *mut xmlChar = ptr::null_mut();
1631 if pi_cmp6(ctxt, b"SYSTEM") {
1632 pi_skip(ctxt, 6);
1633 pi_skip_blanks(ctxt);
1634 uri = pi_parse_system_literal(ctxt);
1635 if uri.is_null() {
1636 pi_fatal_err(ctxt, XML_ERR_URI_REQUIRED);
1637 }
1638 } else if pi_cmp6(ctxt, b"PUBLIC") {
1639 pi_skip(ctxt, 6);
1640 pi_skip_blanks(ctxt);
1641 *public_id = pi_parse_pubid_literal(ctxt);
1642 if public_id.is_null() || (*public_id).is_null() {
1643 pi_fatal_err(ctxt, XML_ERR_PUBID_REQUIRED);
1644 }
1645 if strict != 0 {
1646 if pi_skip_blanks(ctxt) == 0 {
1647 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
1648 }
1649 } else {
1650 if pi_skip_blanks(ctxt) == 0 {
1651 return ptr::null_mut();
1652 }
1653 if pi_raw(ctxt) != b'\'' && pi_raw(ctxt) != b'"' {
1654 return ptr::null_mut();
1655 }
1656 }
1657 uri = pi_parse_system_literal(ctxt);
1658 if uri.is_null() {
1659 pi_fatal_err(ctxt, XML_ERR_URI_REQUIRED);
1660 }
1661 }
1662 uri
1663 }
1664}
1665
1666unsafe fn pi_parse_pi_target(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
1668 unsafe {
1669 let name = pi_parse_name(ctxt);
1670 if name.is_null() {
1671 return ptr::null();
1672 }
1673 let len = crate::abi::exports_xml2::xmlStrlen(name) as usize;
1674 if len >= 3 {
1675 let c0 = *name;
1676 let c1 = *name.add(1);
1677 let c2 = *name.add(2);
1678 if (c0 == b'x' || c0 == b'X')
1679 && (c1 == b'm' || c1 == b'M')
1680 && (c2 == b'l' || c2 == b'L')
1681 {
1682 if len == 3 {
1684 pi_fatal_err(ctxt, XML_ERR_RESERVED_XML_NAME);
1685 } else if !(c0 == b'x' && c1 == b'm' && c2 == b'l') {
1686 pi_fatal_err(ctxt, XML_ERR_RESERVED_XML_NAME);
1687 }
1688 }
1689 }
1690 if !crate::abi::exports_xml2::xmlStrchr(name, b':').is_null() {
1691 }
1693 name
1694 }
1695}
1696
1697unsafe fn pi_parse_pi(ctxt: *mut _xmlParserCtxt) {
1699 unsafe {
1700 if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'?' {
1701 pi_skip(ctxt, 2);
1702 let target = pi_parse_pi_target(ctxt);
1703 if !target.is_null() {
1704 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
1705 pi_skip(ctxt, 2);
1706 pi_sax_pi(ctxt, target, &[]);
1707 xmlFreeImpl(target as *mut c_void);
1708 return;
1709 }
1710 if pi_skip_blanks(ctxt) == 0 {
1711 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
1712 }
1713 let mut buf: Vec<u8> = Vec::new();
1714 loop {
1715 let (cur, l) = pi_current_char_recover(ctxt);
1716 if !pi_is_char(cur) || (cur == b'?' as c_int && pi_nxt(ctxt, 1) == b'>') {
1717 break;
1718 }
1719 pi_push_codepoint(&mut buf, cur);
1720 pi_nextl(ctxt, l);
1721 }
1722 if pi_raw(ctxt) != b'?' {
1723 pi_fatal_err(ctxt, XML_ERR_PI_NOT_FINISHED);
1724 } else {
1725 pi_skip(ctxt, 2);
1726 pi_sax_pi(ctxt, target, &buf);
1727 }
1728 xmlFreeImpl(target as *mut c_void);
1729 } else {
1730 pi_fatal_err(ctxt, XML_ERR_PI_NOT_STARTED);
1731 }
1732 }
1733 }
1734}
1735
1736unsafe fn pi_parse_comment(ctxt: *mut _xmlParserCtxt) {
1738 unsafe {
1739 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
1740 return;
1741 }
1742 pi_skip(ctxt, 2);
1743 if pi_raw(ctxt) != b'-' || pi_nxt(ctxt, 1) != b'-' {
1744 return;
1745 }
1746 pi_skip(ctxt, 2);
1747
1748 let mut buf: Vec<u8> = Vec::new();
1749 let (mut q, ql) = pi_current_char_recover(ctxt);
1750 if q == 0 {
1751 pi_fatal_err(ctxt, XML_ERR_COMMENT_NOT_FINISHED);
1752 return;
1753 }
1754 pi_nextl(ctxt, ql);
1755 let (mut r, rl) = pi_current_char_recover(ctxt);
1756 if r == 0 {
1757 pi_fatal_err(ctxt, XML_ERR_COMMENT_NOT_FINISHED);
1758 return;
1759 }
1760 pi_nextl(ctxt, rl);
1761 let (mut cur, mut l) = pi_current_char_recover(ctxt);
1762 while pi_is_char(cur) && !(cur == b'>' as c_int && r == b'-' as c_int && q == b'-' as c_int)
1763 {
1764 if r == b'-' as c_int && q == b'-' as c_int {
1765 pi_fatal_err(ctxt, XML_ERR_HYPHEN_IN_COMMENT);
1766 }
1767 pi_push_codepoint(&mut buf, q);
1768 q = r;
1769 r = cur;
1770 pi_nextl(ctxt, l);
1771 let (c2, l2) = pi_current_char_recover(ctxt);
1772 cur = c2;
1773 l = l2;
1774 }
1775 if cur == 0 {
1776 pi_fatal_err(ctxt, XML_ERR_COMMENT_NOT_FINISHED);
1777 return;
1778 }
1779 if !pi_is_char(cur) {
1780 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1781 return;
1782 }
1783 pi_next1(ctxt);
1784 pi_sax_comment(ctxt, &buf);
1785 }
1786}
1787
1788unsafe fn pi_parse_char_data(ctxt: *mut _xmlParserCtxt, _cdata: c_int) {
1790 unsafe {
1791 let mut buf: Vec<u8> = Vec::new();
1792 loop {
1793 if pi_stopped(ctxt) {
1794 break;
1795 }
1796 let input = pi_input(ctxt);
1797 if input.is_null() {
1798 break;
1799 }
1800 if (*input).cur >= (*input).end {
1801 break;
1802 }
1803 let c = pi_raw(ctxt);
1804 if c == b'<' || c == b'&' {
1805 break;
1806 }
1807 buf.push(c);
1808 pi_next1(ctxt);
1809 }
1810 if buf.is_empty() {
1811 return;
1812 }
1813 let all_ws = buf.iter().all(|&b| pi_is_blank_ch(b));
1815 let keep_blanks = (*ctxt).keepBlanks != 0;
1816 let ignorable = all_ws && !keep_blanks;
1817 pi_sax_chars(ctxt, &buf, ignorable);
1818 }
1819}
1820
1821unsafe fn pi_parse_cd_sect(ctxt: *mut _xmlParserCtxt) {
1823 unsafe {
1824 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' || pi_nxt(ctxt, 2) != b'[' {
1825 return;
1826 }
1827 pi_skip(ctxt, 3);
1828 if !pi_cmp6(ctxt, b"CDATA[") {
1829 return;
1830 }
1831 pi_skip(ctxt, 6);
1832
1833 let mut buf: Vec<u8> = Vec::new();
1834 let (mut r, rl) = pi_current_char_recover(ctxt);
1835 if !pi_is_char(r) {
1836 pi_fatal_err(ctxt, XML_ERR_CDATA_NOT_FINISHED);
1837 return;
1838 }
1839 pi_nextl(ctxt, rl);
1840 let (mut s, sl) = pi_current_char_recover(ctxt);
1841 if !pi_is_char(s) {
1842 pi_fatal_err(ctxt, XML_ERR_CDATA_NOT_FINISHED);
1843 return;
1844 }
1845 pi_nextl(ctxt, sl);
1846 let (mut cur, mut l) = pi_current_char_recover(ctxt);
1847 while pi_is_char(cur)
1848 && !(r == b']' as c_int && s == b']' as c_int && cur == b'>' as c_int)
1849 {
1850 pi_push_codepoint(&mut buf, r);
1851 r = s;
1852 s = cur;
1853 pi_nextl(ctxt, l);
1854 let (c2, l2) = pi_current_char_recover(ctxt);
1855 cur = c2;
1856 l = l2;
1857 }
1858 if cur != b'>' as c_int {
1859 pi_fatal_err(ctxt, XML_ERR_CDATA_NOT_FINISHED);
1860 return;
1861 }
1862 pi_nextl(ctxt, l);
1863
1864 let c = &*ctxt;
1866 if !c.sax.is_null() && c.disableSAX == 0 {
1867 let buf_p = pi_strndup_bytes(buf.as_ptr(), buf.len());
1868 if !buf_p.is_null() {
1869 let sax = &*c.sax;
1870 if sax.cdataBlock.is_some() && (c.options & XML_PARSE_NOCDATA) == 0 {
1871 SaxDispatcher::cdata_block(sax, c.userData, buf_p, buf.len() as c_int);
1872 } else {
1873 SaxDispatcher::characters(sax, c.userData, buf_p, buf.len() as c_int);
1874 }
1875 xmlFreeImpl(buf_p as *mut c_void);
1876 }
1877 }
1878 }
1879}
1880
1881unsafe fn pi_parse_reference(ctxt: *mut _xmlParserCtxt) {
1883 unsafe {
1884 if pi_raw(ctxt) != b'&' {
1885 return;
1886 }
1887 if pi_nxt(ctxt, 1) == b'#' {
1889 let value = pi_parse_char_ref(ctxt);
1890 if value == 0 {
1891 return;
1892 }
1893 let mut out = Vec::new();
1894 pi_push_codepoint(&mut out, value);
1895 pi_sax_chars(ctxt, &out, false);
1896 return;
1897 }
1898
1899 let name = pi_parse_entity_ref_name(ctxt);
1901 if name.is_null() {
1902 return;
1903 }
1904 let ent = pi_lookup_general_entity(ctxt, name);
1905 if ent.is_null() {
1906 let c = &*ctxt;
1908 if c.replaceEntities == 0
1909 && !c.sax.is_null()
1910 && c.disableSAX == 0
1911 && (*c.sax).reference.is_some()
1912 {
1913 SaxDispatcher::reference(&*c.sax, c.userData, name);
1914 }
1915 xmlFreeImpl(name as *mut c_void);
1916 return;
1917 }
1918 if (*ctxt).wellFormed == 0 {
1919 xmlFreeImpl(name as *mut c_void);
1920 return;
1921 }
1922
1923 let etype = (*ent).etype;
1925 if etype == XML_INTERNAL_PREDEFINED_ENTITY as c_int {
1926 let val = (*ent).content;
1927 if !val.is_null() {
1928 let l = crate::abi::exports_xml2::xmlStrlen(val) as usize;
1929 let bytes = core::slice::from_raw_parts(val, l);
1930 pi_sax_chars(ctxt, bytes, false);
1931 }
1932 xmlFreeImpl(name as *mut c_void);
1933 return;
1934 }
1935
1936 let c = &*ctxt;
1937 if c.replaceEntities == 0 {
1938 if !c.sax.is_null() && c.disableSAX == 0 && (*c.sax).reference.is_some() {
1940 SaxDispatcher::reference(&*c.sax, c.userData, (*ent).name);
1941 }
1942 } else if etype == XML_INTERNAL_GENERAL_ENTITY as c_int && !(*ent).content.is_null() {
1943 let val = (*ent).content;
1945 let l = crate::abi::exports_xml2::xmlStrlen(val) as usize;
1946 let bytes = core::slice::from_raw_parts(val, l);
1947 pi_sax_chars(ctxt, bytes, false);
1948 }
1949 xmlFreeImpl(name as *mut c_void);
1950 }
1951}
1952
1953unsafe fn pi_parse_pe_reference(ctxt: *mut _xmlParserCtxt) {
1956 unsafe {
1957 if pi_raw(ctxt) != b'%' {
1958 return;
1959 }
1960 pi_next1(ctxt);
1961 let name = pi_parse_name(ctxt);
1962 if name.is_null() {
1963 pi_fatal_err(ctxt, XML_ERR_PEREF_NO_NAME);
1964 return;
1965 }
1966 if pi_raw(ctxt) != b';' {
1967 pi_fatal_err(ctxt, XML_ERR_PEREF_SEMICOL_MISSING);
1968 xmlFreeImpl(name as *mut c_void);
1969 return;
1970 }
1971 pi_next1(ctxt);
1972
1973 let ent = pi_lookup_parameter_entity(ctxt, name);
1974 if ent.is_null() {
1975 pi_fatal_err(ctxt, XML_ERR_UNDECLARED_ENTITY);
1976 xmlFreeImpl(name as *mut c_void);
1977 return;
1978 }
1979 (*ctxt).hasPErefs = 1;
1980
1981 if (*ent).etype == XML_INTERNAL_PARAMETER_ENTITY as c_int && !(*ent).content.is_null() {
1982 let content = (*ent).content;
1983 let clen = crate::abi::exports_xml2::xmlStrlen(content) as usize;
1984 let total = clen + 3;
1986 let buf = xmlMallocImpl(total) as *mut xmlChar;
1987 if !buf.is_null() {
1988 *buf = b' ';
1989 ptr::copy_nonoverlapping(content, buf.add(1), clen);
1990 *buf.add(clen + 1) = b' ';
1991 *buf.add(clen + 2) = 0;
1992 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
1993 if !input.is_null() {
1994 (*input).base = buf;
1995 (*input).cur = buf;
1996 (*input).end = buf.add(clen + 1);
1997 (*input).line = (*(*ctxt).input).line;
1998 (*input).col = (*(*ctxt).input).col;
1999 (*input).entity = ent;
2000 pi_input_push(ctxt, input);
2001 } else {
2002 xmlFreeImpl(buf as *mut c_void);
2003 }
2004 }
2005 }
2006 xmlFreeImpl(name as *mut c_void);
2007 }
2008}
2009
2010unsafe fn pi_parse_notation_decl(ctxt: *mut _xmlParserCtxt) {
2012 unsafe {
2013 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2014 return;
2015 }
2016 pi_skip(ctxt, 2);
2017 if pi_cmp8(ctxt, b"NOTATION") {
2018 pi_skip(ctxt, 8);
2019 if pi_skip_blanks(ctxt) == 0 {
2020 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2021 return;
2022 }
2023 let name = pi_parse_name(ctxt);
2024 if name.is_null() {
2025 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_STARTED);
2026 return;
2027 }
2028 if pi_skip_blanks(ctxt) == 0 {
2029 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2030 xmlFreeImpl(name as *mut c_void);
2031 return;
2032 }
2033 let mut pubid: *mut xmlChar = ptr::null_mut();
2034 let systemid = pi_parse_external_id(ctxt, &mut pubid, 0);
2035 pi_skip_blanks(ctxt);
2036 if pi_raw(ctxt) == b'>' {
2037 pi_next1(ctxt);
2038 let c = &*ctxt;
2039 if !c.sax.is_null() && c.disableSAX == 0 {
2040 SaxDispatcher::notation_decl(&*c.sax, c.userData, name, pubid, systemid);
2041 }
2042 } else {
2043 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_FINISHED);
2044 }
2045 if !systemid.is_null() {
2046 xmlFreeImpl(systemid as *mut c_void);
2047 }
2048 if !pubid.is_null() {
2049 xmlFreeImpl(pubid as *mut c_void);
2050 }
2051 xmlFreeImpl(name as *mut c_void);
2052 }
2053 }
2054}
2055
2056unsafe fn pi_parse_entity_decl(ctxt: *mut _xmlParserCtxt) {
2058 unsafe {
2059 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2060 return;
2061 }
2062 pi_skip(ctxt, 2);
2063 if pi_cmp6(ctxt, b"ENTITY") {
2064 pi_skip(ctxt, 6);
2065 if pi_skip_blanks(ctxt) == 0 {
2066 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2067 }
2068 let mut is_parameter = false;
2069 if pi_raw(ctxt) == b'%' {
2070 pi_next1(ctxt);
2071 if pi_skip_blanks(ctxt) == 0 {
2072 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2073 }
2074 is_parameter = true;
2075 }
2076 let name = pi_parse_name(ctxt);
2077 if name.is_null() {
2078 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2079 return;
2080 }
2081 if pi_skip_blanks(ctxt) == 0 {
2082 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2083 }
2084
2085 let mut value: *mut xmlChar = ptr::null_mut();
2086 let mut uri: *mut xmlChar = ptr::null_mut();
2087 let mut literal: *mut xmlChar = ptr::null_mut();
2088 let mut ndata: *const xmlChar = ptr::null();
2089 let mut orig: *mut xmlChar = ptr::null_mut();
2090
2091 if is_parameter {
2092 if pi_raw(ctxt) == b'"' || pi_raw(ctxt) == b'\'' {
2093 value = pi_parse_entity_value(ctxt, &mut orig);
2094 if !value.is_null() {
2095 let c = &*ctxt;
2096 if !c.sax.is_null() && c.disableSAX == 0 {
2097 SaxDispatcher::entity_decl(
2098 &*c.sax,
2099 c.userData,
2100 name,
2101 XML_INTERNAL_PARAMETER_ENTITY as c_int,
2102 ptr::null(),
2103 ptr::null(),
2104 value,
2105 );
2106 }
2107 }
2108 } else {
2109 uri = pi_parse_external_id(ctxt, &mut literal, 1);
2110 if !uri.is_null() {
2111 let c = &*ctxt;
2112 if !c.sax.is_null() && c.disableSAX == 0 {
2113 SaxDispatcher::entity_decl(
2114 &*c.sax,
2115 c.userData,
2116 name,
2117 XML_EXTERNAL_PARAMETER_ENTITY as c_int,
2118 literal,
2119 uri,
2120 ptr::null_mut(),
2121 );
2122 }
2123 }
2124 }
2125 } else {
2126 if pi_raw(ctxt) == b'"' || pi_raw(ctxt) == b'\'' {
2127 value = pi_parse_entity_value(ctxt, &mut orig);
2128 let c = &*ctxt;
2129 if !c.sax.is_null() && c.disableSAX == 0 {
2130 SaxDispatcher::entity_decl(
2131 &*c.sax,
2132 c.userData,
2133 name,
2134 XML_INTERNAL_GENERAL_ENTITY as c_int,
2135 ptr::null(),
2136 ptr::null(),
2137 value,
2138 );
2139 }
2140 } else {
2141 uri = pi_parse_external_id(ctxt, &mut literal, 1);
2142 if pi_raw(ctxt) != b'>' && pi_skip_blanks(ctxt) == 0 {
2143 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2144 }
2145 if pi_cmp5(ctxt, b"NDATA") {
2146 pi_skip(ctxt, 5);
2147 if pi_skip_blanks(ctxt) == 0 {
2148 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2149 }
2150 ndata = pi_parse_name(ctxt);
2151 let c = &*ctxt;
2152 if !c.sax.is_null() && c.disableSAX == 0 {
2153 SaxDispatcher::unparsed_entity_decl(
2154 &*c.sax,
2155 c.userData,
2156 name,
2157 literal,
2158 uri,
2159 ndata,
2160 );
2161 }
2162 if !ndata.is_null() {
2163 xmlFreeImpl(ndata as *mut c_void);
2164 }
2165 } else {
2166 let c = &*ctxt;
2167 if !c.sax.is_null() && c.disableSAX == 0 {
2168 SaxDispatcher::entity_decl(
2169 &*c.sax,
2170 c.userData,
2171 name,
2172 XML_EXTERNAL_GENERAL_PARSED_ENTITY as c_int,
2173 literal,
2174 uri,
2175 ptr::null_mut(),
2176 );
2177 }
2178 }
2179 }
2180 }
2181
2182 pi_skip_blanks(ctxt);
2183 if pi_raw(ctxt) != b'>' {
2184 pi_fatal_err(ctxt, XML_ERR_ENTITY_NOT_FINISHED);
2185 } else {
2186 pi_next1(ctxt);
2187 }
2188
2189 if !orig.is_null() {
2190 let c = &*ctxt;
2192 let mut cur: *mut _xmlEntity = ptr::null_mut();
2193 if !c.sax.is_null() {
2194 if is_parameter {
2195 if (*c.sax).getParameterEntity.is_some() {
2196 cur = SaxDispatcher::get_parameter_entity(&*c.sax, c.userData, name);
2197 }
2198 } else if (*c.sax).getEntity.is_some() {
2199 cur = SaxDispatcher::get_entity(&*c.sax, c.userData, name);
2200 }
2201 }
2202 if !cur.is_null() && (*cur).orig.is_null() {
2203 (*cur).orig = orig;
2204 orig = ptr::null_mut();
2205 }
2206 }
2207
2208 if !value.is_null() {
2209 xmlFreeImpl(value as *mut c_void);
2210 }
2211 if !uri.is_null() {
2212 xmlFreeImpl(uri as *mut c_void);
2213 }
2214 if !literal.is_null() {
2215 xmlFreeImpl(literal as *mut c_void);
2216 }
2217 if !orig.is_null() {
2218 xmlFreeImpl(orig as *mut c_void);
2219 }
2220 xmlFreeImpl(name as *mut c_void);
2221 }
2222 }
2223}
2224
2225unsafe fn pi_parse_default_decl(ctxt: *mut _xmlParserCtxt, value: *mut *mut xmlChar) -> c_int {
2227 unsafe {
2228 *value = ptr::null_mut();
2229 if pi_cmp9(ctxt, b"#REQUIRED") {
2230 pi_skip(ctxt, 9);
2231 return XML_ATTRIBUTE_REQUIRED;
2232 }
2233 if pi_cmp8(ctxt, b"#IMPLIED") {
2234 pi_skip(ctxt, 8);
2235 return XML_ATTRIBUTE_IMPLIED;
2236 }
2237 let mut val = XML_ATTRIBUTE_NONE;
2238 if pi_cmp6(ctxt, b"#FIXED") {
2239 pi_skip(ctxt, 6);
2240 val = XML_ATTRIBUTE_FIXED;
2241 if pi_skip_blanks(ctxt) == 0 {
2242 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2243 }
2244 }
2245 let ret = pi_parse_att_value(ctxt);
2246 if ret.is_null() {
2247 pi_fatal_err(ctxt, (*ctxt).errNo);
2248 } else {
2249 *value = ret;
2250 }
2251 val
2252 }
2253}
2254
2255unsafe fn pi_parse_attribute_type(ctxt: *mut _xmlParserCtxt, tree: *mut *mut _xmlEnumeration) -> c_int {
2257 unsafe {
2258 if pi_cmp5(ctxt, b"CDATA") {
2259 pi_skip(ctxt, 5);
2260 XML_ATTRIBUTE_CDATA
2261 } else if pi_cmp6(ctxt, b"IDREFS") {
2262 pi_skip(ctxt, 6);
2263 XML_ATTRIBUTE_IDREFS
2264 } else if pi_cmp5(ctxt, b"IDREF") {
2265 pi_skip(ctxt, 5);
2266 XML_ATTRIBUTE_IDREF
2267 } else if pi_raw(ctxt) == b'I' && pi_nxt(ctxt, 1) == b'D' {
2268 pi_skip(ctxt, 2);
2269 XML_ATTRIBUTE_ID
2270 } else if pi_cmp6(ctxt, b"ENTITY") {
2271 pi_skip(ctxt, 6);
2272 XML_ATTRIBUTE_ENTITY
2273 } else if pi_cmp8(ctxt, b"ENTITIES") {
2274 pi_skip(ctxt, 8);
2275 XML_ATTRIBUTE_ENTITIES
2276 } else if pi_cmp8(ctxt, b"NMTOKENS") {
2277 pi_skip(ctxt, 8);
2278 XML_ATTRIBUTE_NMTOKENS
2279 } else if pi_cmp7(ctxt, b"NMTOKEN") {
2280 pi_skip(ctxt, 7);
2281 XML_ATTRIBUTE_NMTOKEN
2282 } else {
2283 pi_parse_enumerated_type(ctxt, tree)
2284 }
2285 }
2286}
2287
2288unsafe fn pi_parse_notation_type(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
2290 unsafe {
2291 if pi_raw(ctxt) != b'(' {
2292 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_STARTED);
2293 return ptr::null_mut();
2294 }
2295 let mut ret: *mut _xmlEnumeration = ptr::null_mut();
2296 let mut last: *mut _xmlEnumeration = ptr::null_mut();
2297 loop {
2298 pi_next1(ctxt);
2299 pi_skip_blanks(ctxt);
2300 let name = pi_parse_name(ctxt);
2301 if name.is_null() {
2302 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2303 pi_free_enumeration(ret);
2304 return ptr::null_mut();
2305 }
2306 let cur = pi_create_enumeration(name);
2307 if cur.is_null() {
2309 pi_err_memory(ctxt);
2310 xmlFreeImpl(name as *mut c_void);
2311 pi_free_enumeration(ret);
2312 return ptr::null_mut();
2313 }
2314 if last.is_null() {
2315 ret = cur;
2316 } else {
2317 (*last).next = cur;
2318 }
2319 last = cur;
2320 pi_skip_blanks(ctxt);
2321 if pi_raw(ctxt) != b'|' {
2322 break;
2323 }
2324 }
2325 if pi_raw(ctxt) != b')' {
2326 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_FINISHED);
2327 pi_free_enumeration(ret);
2328 return ptr::null_mut();
2329 }
2330 pi_next1(ctxt);
2331 ret
2332 }
2333}
2334
2335unsafe fn pi_parse_enumeration_type(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
2337 unsafe {
2338 if pi_raw(ctxt) != b'(' {
2339 pi_fatal_err(ctxt, XML_ERR_ATTLIST_NOT_STARTED);
2340 return ptr::null_mut();
2341 }
2342 let mut ret: *mut _xmlEnumeration = ptr::null_mut();
2343 let mut last: *mut _xmlEnumeration = ptr::null_mut();
2344 loop {
2345 pi_next1(ctxt);
2346 pi_skip_blanks(ctxt);
2347 let name = pi_parse_nmtoken(ctxt);
2348 if name.is_null() {
2349 pi_fatal_err(ctxt, XML_ERR_NMTOKEN_REQUIRED);
2350 return ret;
2351 }
2352 let cur = pi_create_enumeration(name);
2353 if cur.is_null() {
2355 pi_err_memory(ctxt);
2356 xmlFreeImpl(name as *mut c_void);
2357 pi_free_enumeration(ret);
2358 return ptr::null_mut();
2359 }
2360 if last.is_null() {
2361 ret = cur;
2362 } else {
2363 (*last).next = cur;
2364 }
2365 last = cur;
2366 pi_skip_blanks(ctxt);
2367 if pi_raw(ctxt) != b'|' {
2368 break;
2369 }
2370 }
2371 if pi_raw(ctxt) != b')' {
2372 pi_fatal_err(ctxt, XML_ERR_ATTLIST_NOT_FINISHED);
2373 return ret;
2374 }
2375 pi_next1(ctxt);
2376 ret
2377 }
2378}
2379
2380unsafe fn pi_parse_enumerated_type(ctxt: *mut _xmlParserCtxt, tree: *mut *mut _xmlEnumeration) -> c_int {
2382 unsafe {
2383 if pi_cmp8(ctxt, b"NOTATION") {
2384 pi_skip(ctxt, 8);
2385 if pi_skip_blanks(ctxt) == 0 {
2386 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2387 return 0;
2388 }
2389 *tree = pi_parse_notation_type(ctxt);
2390 if tree.is_null() || (*tree).is_null() {
2391 return 0;
2392 }
2393 return XML_ATTRIBUTE_NOTATION;
2394 }
2395 *tree = pi_parse_enumeration_type(ctxt);
2396 if tree.is_null() || (*tree).is_null() {
2397 return 0;
2398 }
2399 XML_ATTRIBUTE_ENUMERATION
2400 }
2401}
2402
2403unsafe fn pi_parse_attribute_list_decl(ctxt: *mut _xmlParserCtxt) {
2405 unsafe {
2406 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2407 return;
2408 }
2409 pi_skip(ctxt, 2);
2410 if pi_cmp7(ctxt, b"ATTLIST") {
2411 pi_skip(ctxt, 7);
2412 if pi_skip_blanks(ctxt) == 0 {
2413 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2414 }
2415 let elem_name = pi_parse_name(ctxt);
2416 if elem_name.is_null() {
2417 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2418 return;
2419 }
2420 pi_skip_blanks(ctxt);
2421 while pi_raw(ctxt) != b'>' && !pi_stopped(ctxt) {
2422 let mut tree: *mut _xmlEnumeration = ptr::null_mut();
2423 let attr_name = pi_parse_name(ctxt);
2424 if attr_name.is_null() {
2425 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2426 break;
2427 }
2428 if pi_skip_blanks(ctxt) == 0 {
2429 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2430 xmlFreeImpl(attr_name as *mut c_void);
2431 break;
2432 }
2433 let type_ = pi_parse_attribute_type(ctxt, &mut tree);
2434 if type_ <= 0 {
2435 xmlFreeImpl(attr_name as *mut c_void);
2436 break;
2437 }
2438 if pi_skip_blanks(ctxt) == 0 {
2439 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2440 if !tree.is_null() {
2441 pi_free_enumeration(tree);
2442 }
2443 xmlFreeImpl(attr_name as *mut c_void);
2444 break;
2445 }
2446 let mut default_value: *mut xmlChar = ptr::null_mut();
2447 let def = pi_parse_default_decl(ctxt, &mut default_value);
2448 if def <= 0 {
2449 if !default_value.is_null() {
2450 xmlFreeImpl(default_value as *mut c_void);
2451 }
2452 if !tree.is_null() {
2453 pi_free_enumeration(tree);
2454 }
2455 xmlFreeImpl(attr_name as *mut c_void);
2456 break;
2457 }
2458 if pi_raw(ctxt) != b'>' {
2459 if pi_skip_blanks(ctxt) == 0 {
2460 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2461 if !default_value.is_null() {
2462 xmlFreeImpl(default_value as *mut c_void);
2463 }
2464 if !tree.is_null() {
2465 pi_free_enumeration(tree);
2466 }
2467 xmlFreeImpl(attr_name as *mut c_void);
2468 break;
2469 }
2470 }
2471 let c = &*ctxt;
2472 if !c.sax.is_null() && c.disableSAX == 0 {
2473 SaxDispatcher::attribute_decl(
2474 &*c.sax,
2475 c.userData,
2476 elem_name,
2477 attr_name,
2478 type_,
2479 def,
2480 default_value,
2481 tree,
2482 );
2483 } else if !tree.is_null() {
2484 pi_free_enumeration(tree);
2485 }
2486 if !default_value.is_null() {
2487 xmlFreeImpl(default_value as *mut c_void);
2488 }
2489 xmlFreeImpl(attr_name as *mut c_void);
2490 }
2491 if pi_raw(ctxt) == b'>' {
2492 pi_next1(ctxt);
2493 }
2494 xmlFreeImpl(elem_name as *mut c_void);
2495 }
2496 }
2497}
2498
2499unsafe fn pi_create_enumeration(name: *const xmlChar) -> *mut _xmlEnumeration {
2501 unsafe {
2502 let cur = xmlMallocZero(size_of::<_xmlEnumeration>()) as *mut _xmlEnumeration;
2503 if !cur.is_null() {
2504 (*cur).name = name;
2505 (*cur).next = ptr::null_mut();
2506 }
2507 cur
2508 }
2509}
2510
2511unsafe fn pi_free_enumeration(cur: *mut _xmlEnumeration) {
2513 unsafe {
2514 let mut cur = cur;
2515 while !cur.is_null() {
2516 let next = (*cur).next;
2517 if !(*cur).name.is_null() {
2518 xmlFreeImpl((*cur).name as *mut c_void);
2519 }
2520 xmlFreeImpl(cur as *mut c_void);
2521 cur = next;
2522 }
2523 }
2524}
2525
2526unsafe fn pi_parse_element_mixed_content_decl(ctxt: *mut _xmlParserCtxt, _open_input_nr: c_int) -> *mut _xmlElementContent {
2528 unsafe {
2529 if pi_cmp7(ctxt, b"#PCDATA") {
2530 pi_skip(ctxt, 7);
2531 pi_skip_blanks(ctxt);
2532 if pi_raw(ctxt) == b')' {
2533 pi_next1(ctxt);
2534 let ret = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2535 if pi_raw(ctxt) == b'*' {
2536 if !ret.is_null() {
2537 (*ret).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2538 }
2539 pi_next1(ctxt);
2540 }
2541 return ret;
2542 }
2543 let mut ret: *mut _xmlElementContent =
2544 create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2545 let mut cur = ret;
2546 let mut elem: *const xmlChar = ptr::null();
2547 while pi_raw(ctxt) == b'|' && !pi_stopped(ctxt) {
2548 pi_next1(ctxt);
2549 let n = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
2550 if n.is_null() {
2551 pi_err_memory(ctxt);
2552 free_content_model(ret);
2553 return ptr::null_mut();
2554 }
2555 if elem.is_null() {
2556 (*n).c1 = cur;
2557 if !cur.is_null() {
2558 (*cur).parent = n;
2559 }
2560 ret = n;
2561 cur = n;
2562 } else {
2563 (*cur).c2 = n;
2564 (*n).parent = cur;
2565 let c1 = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2566 xmlFreeImpl(elem as *mut c_void);
2567 (*n).c1 = c1;
2568 if !c1.is_null() {
2569 (*c1).parent = n;
2570 }
2571 cur = n;
2572 }
2573 pi_skip_blanks(ctxt);
2574 elem = pi_parse_name(ctxt);
2575 if elem.is_null() {
2576 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2577 free_content_model(ret);
2578 return ptr::null_mut();
2579 }
2580 pi_skip_blanks(ctxt);
2581 }
2582 if pi_raw(ctxt) == b')' && pi_nxt(ctxt, 1) == b'*' {
2583 if !elem.is_null() {
2584 let c2 = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2585 xmlFreeImpl(elem as *mut c_void);
2586 if !cur.is_null() {
2587 (*cur).c2 = c2;
2588 if !c2.is_null() {
2589 (*c2).parent = cur;
2590 }
2591 }
2592 }
2593 if !ret.is_null() {
2594 (*ret).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2595 }
2596 pi_skip(ctxt, 2);
2597 } else {
2598 if !elem.is_null() {
2599 xmlFreeImpl(elem as *mut c_void);
2600 }
2601 free_content_model(ret);
2602 pi_fatal_err(ctxt, XML_ERR_MIXED_NOT_STARTED);
2603 return ptr::null_mut();
2604 }
2605 return ret;
2606 }
2607 pi_fatal_err(ctxt, XML_ERR_PCDATA_REQUIRED);
2608 ptr::null_mut()
2609 }
2610}
2611
2612unsafe fn pi_parse_element_children_content_decl_priv(
2614 ctxt: *mut _xmlParserCtxt,
2615 _open_input_nr: c_int,
2616 depth: c_int,
2617) -> *mut _xmlElementContent {
2618 unsafe {
2619 let max_depth = if (*ctxt).options & XML_PARSE_HUGE != 0 { 2048 } else { 256 };
2620 if depth > max_depth {
2621 pi_fatal_err(ctxt, XML_ERR_RESOURCE_LIMIT);
2622 return ptr::null_mut();
2623 }
2624 pi_skip_blanks(ctxt);
2625 let mut ret: *mut _xmlElementContent = ptr::null_mut();
2626 let mut cur: *mut _xmlElementContent = ptr::null_mut();
2627 let mut last: *mut _xmlElementContent = ptr::null_mut();
2628 let mut type_: u8 = 0;
2629
2630 if pi_raw(ctxt) == b'(' {
2631 pi_next1(ctxt);
2632 cur = pi_parse_element_children_content_decl_priv(ctxt, (*ctxt).inputNr, depth + 1);
2633 if cur.is_null() {
2634 return ptr::null_mut();
2635 }
2636 ret = cur;
2637 } else {
2638 let elem = pi_parse_name(ctxt);
2639 if elem.is_null() {
2640 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2641 return ptr::null_mut();
2642 }
2643 cur = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2644 xmlFreeImpl(elem as *mut c_void);
2645 if cur.is_null() {
2646 pi_err_memory(ctxt);
2647 return ptr::null_mut();
2648 }
2649 ret = cur;
2650 if pi_raw(ctxt) == b'?' {
2651 (*cur).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2652 pi_next1(ctxt);
2653 } else if pi_raw(ctxt) == b'*' {
2654 (*cur).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2655 pi_next1(ctxt);
2656 } else if pi_raw(ctxt) == b'+' {
2657 (*cur).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2658 pi_next1(ctxt);
2659 } else {
2660 (*cur).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
2661 }
2662 }
2663
2664 while !pi_stopped(ctxt) {
2665 pi_skip_blanks(ctxt);
2666 if pi_raw(ctxt) == b')' {
2667 break;
2668 }
2669 if pi_raw(ctxt) == b',' || pi_raw(ctxt) == b'|' {
2670 let sep = pi_raw(ctxt);
2671 if type_ == 0 {
2672 type_ = sep;
2673 } else if type_ != sep {
2674 pi_fatal_err(ctxt, XML_ERR_SEPARATOR_REQUIRED);
2675 free_content_model(ret);
2676 return ptr::null_mut();
2677 }
2678 pi_next1(ctxt);
2679 let op_type = if sep == b',' {
2680 XML_ELEMENT_CONTENT_SEQ as c_int
2681 } else {
2682 XML_ELEMENT_CONTENT_OR as c_int
2683 };
2684 let op = create_content_model(ptr::null(), op_type);
2685 if op.is_null() {
2686 pi_err_memory(ctxt);
2687 free_content_model(ret);
2688 return ptr::null_mut();
2689 }
2690 if last.is_null() {
2691 (*op).c1 = ret;
2692 if !ret.is_null() {
2693 (*ret).parent = op;
2694 }
2695 ret = op;
2696 cur = op;
2697 } else {
2698 (*cur).c2 = op;
2699 (*op).parent = cur;
2700 (*op).c1 = last;
2701 if !last.is_null() {
2702 (*last).parent = op;
2703 }
2704 cur = op;
2705 last = ptr::null_mut();
2706 }
2707 } else {
2708 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED);
2709 free_content_model(ret);
2710 return ptr::null_mut();
2711 }
2712
2713 pi_skip_blanks(ctxt);
2714 if pi_raw(ctxt) == b'(' {
2715 pi_next1(ctxt);
2716 last = pi_parse_element_children_content_decl_priv(ctxt, (*ctxt).inputNr, depth + 1);
2717 if last.is_null() {
2718 free_content_model(ret);
2719 return ptr::null_mut();
2720 }
2721 } else {
2722 let elem = pi_parse_name(ctxt);
2723 if elem.is_null() {
2724 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2725 free_content_model(ret);
2726 return ptr::null_mut();
2727 }
2728 last = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2729 xmlFreeImpl(elem as *mut c_void);
2730 if last.is_null() {
2731 pi_err_memory(ctxt);
2732 free_content_model(ret);
2733 return ptr::null_mut();
2734 }
2735 if pi_raw(ctxt) == b'?' {
2736 (*last).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2737 pi_next1(ctxt);
2738 } else if pi_raw(ctxt) == b'*' {
2739 (*last).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2740 pi_next1(ctxt);
2741 } else if pi_raw(ctxt) == b'+' {
2742 (*last).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2743 pi_next1(ctxt);
2744 } else {
2745 (*last).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
2746 }
2747 }
2748 }
2749
2750 if !cur.is_null() && !last.is_null() {
2751 (*cur).c2 = last;
2752 (*last).parent = cur;
2753 }
2754 pi_next1(ctxt);
2755 if pi_raw(ctxt) == b'?' {
2756 if !ret.is_null() {
2757 (*ret).ocur = if (*ret).ocur == XML_ELEMENT_CONTENT_PLUS as c_int
2758 || (*ret).ocur == XML_ELEMENT_CONTENT_MULT as c_int
2759 {
2760 XML_ELEMENT_CONTENT_MULT as c_int
2761 } else {
2762 XML_ELEMENT_CONTENT_OPT as c_int
2763 };
2764 }
2765 pi_next1(ctxt);
2766 } else if pi_raw(ctxt) == b'*' {
2767 if !ret.is_null() {
2768 (*ret).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2769 }
2770 pi_next1(ctxt);
2771 } else if pi_raw(ctxt) == b'+' {
2772 if !ret.is_null() {
2773 (*ret).ocur = if (*ret).ocur == XML_ELEMENT_CONTENT_OPT as c_int
2774 || (*ret).ocur == XML_ELEMENT_CONTENT_MULT as c_int
2775 {
2776 XML_ELEMENT_CONTENT_MULT as c_int
2777 } else {
2778 XML_ELEMENT_CONTENT_PLUS as c_int
2779 };
2780 }
2781 pi_next1(ctxt);
2782 }
2783 ret
2784 }
2785}
2786
2787unsafe fn pi_parse_element_content_decl(
2789 ctxt: *mut _xmlParserCtxt,
2790 name: *const xmlChar,
2791 result: *mut *mut _xmlElementContent,
2792) -> c_int {
2793 unsafe {
2794 *result = ptr::null_mut();
2795 if pi_raw(ctxt) != b'(' {
2796 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2797 return -1;
2798 }
2799 let open_input_nr = (*ctxt).inputNr;
2800 pi_next1(ctxt);
2801 pi_skip_blanks(ctxt);
2802 let tree;
2803 let res;
2804 if pi_cmp7(ctxt, b"#PCDATA") {
2805 tree = pi_parse_element_mixed_content_decl(ctxt, open_input_nr);
2806 res = XML_ELEMENT_TYPE_MIXED;
2807 } else {
2808 tree = pi_parse_element_children_content_decl_priv(ctxt, open_input_nr, 1);
2809 res = XML_ELEMENT_TYPE_ELEMENT;
2810 }
2811 if tree.is_null() {
2812 return -1;
2813 }
2814 pi_skip_blanks(ctxt);
2815 *result = tree;
2816 res
2817 }
2818}
2819
2820unsafe fn pi_parse_element_decl(ctxt: *mut _xmlParserCtxt) -> c_int {
2822 unsafe {
2823 let mut ret = -1;
2824 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2825 return ret;
2826 }
2827 pi_skip(ctxt, 2);
2828 if pi_cmp7(ctxt, b"ELEMENT") {
2829 pi_skip(ctxt, 7);
2830 if pi_skip_blanks(ctxt) == 0 {
2831 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2832 return -1;
2833 }
2834 let name = pi_parse_name(ctxt);
2835 if name.is_null() {
2836 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2837 return -1;
2838 }
2839 if pi_skip_blanks(ctxt) == 0 {
2840 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2841 }
2842 let mut content: *mut _xmlElementContent = ptr::null_mut();
2843 if pi_cmp5(ctxt, b"EMPTY") {
2844 pi_skip(ctxt, 5);
2845 ret = XML_ELEMENT_TYPE_EMPTY;
2846 } else if pi_raw(ctxt) == b'A' && pi_nxt(ctxt, 1) == b'N' && pi_nxt(ctxt, 2) == b'Y' {
2847 pi_skip(ctxt, 3);
2848 ret = XML_ELEMENT_TYPE_ANY;
2849 } else if pi_raw(ctxt) == b'(' {
2850 ret = pi_parse_element_content_decl(ctxt, name, &mut content);
2851 if ret <= 0 {
2852 xmlFreeImpl(name as *mut c_void);
2853 return -1;
2854 }
2855 } else {
2856 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2857 xmlFreeImpl(name as *mut c_void);
2858 return -1;
2859 }
2860
2861 pi_skip_blanks(ctxt);
2862 if pi_raw(ctxt) != b'>' {
2863 pi_fatal_err(ctxt, XML_ERR_GT_REQUIRED);
2864 if !content.is_null() {
2865 free_content_model(content);
2866 }
2867 } else {
2868 pi_next1(ctxt);
2869 let c = &*ctxt;
2870 if !c.sax.is_null() && c.disableSAX == 0 && (*c.sax).elementDecl.is_some() {
2871 if !content.is_null() {
2872 (*content).parent = ptr::null_mut();
2873 }
2874 SaxDispatcher::element_decl(&*c.sax, c.userData, name, ret, content);
2875 if !content.is_null() && (*content).parent.is_null() {
2876 free_content_model(content);
2878 }
2879 } else if !content.is_null() {
2880 free_content_model(content);
2881 }
2882 }
2883 xmlFreeImpl(name as *mut c_void);
2884 }
2885 ret
2886 }
2887}
2888
2889unsafe fn pi_parse_markup_decl(ctxt: *mut _xmlParserCtxt) {
2891 unsafe {
2892 if pi_raw(ctxt) == b'<' {
2893 if pi_nxt(ctxt, 1) == b'!' {
2894 match pi_nxt(ctxt, 2) {
2895 b'E' => {
2896 if pi_nxt(ctxt, 3) == b'L' {
2897 pi_parse_element_decl(ctxt);
2898 } else if pi_nxt(ctxt, 3) == b'N' {
2899 pi_parse_entity_decl(ctxt);
2900 } else {
2901 pi_skip(ctxt, 2);
2902 }
2903 }
2904 b'A' => pi_parse_attribute_list_decl(ctxt),
2905 b'N' => pi_parse_notation_decl(ctxt),
2906 b'-' => pi_parse_comment(ctxt),
2907 _ => {
2908 pi_fatal_err(
2909 ctxt,
2910 if (*ctxt).inSubset == 2 {
2911 XML_ERR_EXT_SUBSET_NOT_FINISHED
2912 } else {
2913 XML_ERR_INT_SUBSET_NOT_FINISHED
2914 },
2915 );
2916 pi_skip(ctxt, 2);
2917 }
2918 }
2919 } else if pi_nxt(ctxt, 1) == b'?' {
2920 pi_parse_pi(ctxt);
2921 }
2922 }
2923 }
2924}
2925
2926unsafe fn pi_parse_text_decl(ctxt: *mut _xmlParserCtxt) {
2928 unsafe {
2929 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
2930 pi_skip(ctxt, 5);
2931 } else {
2932 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_STARTED);
2933 return;
2934 }
2935 if pi_skip_blanks(ctxt) == 0 {
2936 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2937 }
2938 let mut version = pi_parse_version_info(ctxt);
2939 if version.is_null() {
2940 version = crate::abi::exports_xml2::xmlStrdup(b"1.0\0".as_ptr() as *const xmlChar);
2941 } else if pi_skip_blanks(ctxt) == 0 {
2942 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2943 }
2944 let input = pi_input(ctxt);
2945 if !input.is_null() {
2946 (*input).version = version;
2947 } else if !version.is_null() {
2948 xmlFreeImpl(version as *mut c_void);
2949 }
2950 pi_parse_encoding_decl(ctxt);
2951 pi_skip_blanks(ctxt);
2952 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
2953 pi_skip(ctxt, 2);
2954 } else if pi_raw(ctxt) == b'>' {
2955 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
2956 pi_next1(ctxt);
2957 } else {
2958 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
2959 while !pi_stopped(ctxt) && pi_raw(ctxt) != 0 {
2960 let c = pi_raw(ctxt);
2961 pi_next1(ctxt);
2962 if c == b'>' {
2963 break;
2964 }
2965 }
2966 }
2967 }
2968}
2969
2970unsafe fn pi_parse_external_subset(
2972 ctxt: *mut _xmlParserCtxt,
2973 public_id: *const xmlChar,
2974 system_id: *const xmlChar,
2975) {
2976 unsafe {
2977 pi_ctxt_late_init(ctxt);
2978 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
2979 pi_parse_text_decl(ctxt);
2980 }
2981 if (*ctxt).myDoc.is_null() {
2982 (*ctxt).myDoc = crate::xml::tree::new_doc(b"1.0\0".as_ptr() as *const xmlChar);
2983 if (*ctxt).myDoc.is_null() {
2984 pi_err_memory(ctxt);
2985 return;
2986 }
2987 (*(*ctxt).myDoc).properties |= XML_DOC_INTERNAL as c_int;
2988 }
2989 if (*(*ctxt).myDoc).intSubset.is_null() {
2990 create_int_subset((*ctxt).myDoc, ptr::null(), public_id, system_id);
2991 }
2992 (*ctxt).inSubset = 2;
2993 let old_input_nr = (*ctxt).inputNr;
2994 pi_skip_blanks(ctxt);
2995 while !pi_stopped(ctxt) {
2996 let input = pi_input(ctxt);
2997 if input.is_null() {
2998 break;
2999 }
3000 if (*input).cur >= (*input).end {
3001 if (*ctxt).inputNr <= old_input_nr {
3002 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3003 break;
3004 }
3005 pi_pop_pe(ctxt);
3006 } else if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'!' && pi_nxt(ctxt, 2) == b'[' {
3007 pi_parse_conditional_sections(ctxt);
3008 } else if pi_raw(ctxt) == b'<' && (pi_nxt(ctxt, 1) == b'!' || pi_nxt(ctxt, 1) == b'?') {
3009 pi_parse_markup_decl(ctxt);
3010 } else if pi_raw(ctxt) == b'%' {
3011 pi_parse_pe_reference(ctxt);
3012 } else {
3013 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3014 while (*ctxt).inputNr > old_input_nr {
3015 pi_pop_pe(ctxt);
3016 }
3017 break;
3018 }
3019 pi_skip_blanks(ctxt);
3020 }
3021 }
3022}
3023
3024unsafe fn pi_parse_conditional_sections(ctxt: *mut _xmlParserCtxt) {
3026 unsafe {
3027 let old_input_nr = (*ctxt).inputNr;
3028 let mut depth: usize = 0;
3029 loop {
3030 if pi_stopped(ctxt) {
3031 return;
3032 }
3033 let input = pi_input(ctxt);
3034 if input.is_null() {
3035 return;
3036 }
3037 if (*input).cur >= (*input).end {
3038 if (*ctxt).inputNr <= old_input_nr {
3039 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3040 return;
3041 }
3042 pi_pop_pe(ctxt);
3043 } else if pi_raw(ctxt) == b'<'
3044 && pi_nxt(ctxt, 1) == b'!'
3045 && pi_nxt(ctxt, 2) == b'['
3046 {
3047 pi_skip(ctxt, 3);
3048 pi_skip_blanks(ctxt);
3049 if pi_cmp7(ctxt, b"INCLUDE") {
3050 pi_skip(ctxt, 7);
3051 pi_skip_blanks(ctxt);
3052 if pi_raw(ctxt) != b'[' {
3053 pi_fatal_err(ctxt, XML_ERR_CONDSEC_INVALID);
3054 return;
3055 }
3056 pi_next1(ctxt);
3057 depth += 1;
3058 } else if pi_cmp6(ctxt, b"IGNORE") {
3059 pi_skip(ctxt, 6);
3060 pi_skip_blanks(ctxt);
3061 if pi_raw(ctxt) != b'[' {
3062 pi_fatal_err(ctxt, XML_ERR_CONDSEC_INVALID);
3063 return;
3064 }
3065 pi_next1(ctxt);
3066 let mut ignore_depth: usize = 0;
3067 loop {
3068 if pi_stopped(ctxt) {
3069 return;
3070 }
3071 let inp = pi_input(ctxt);
3072 if inp.is_null() || (*inp).cur >= (*inp).end || pi_raw(ctxt) == 0 {
3073 pi_fatal_err(ctxt, XML_ERR_CONDSEC_NOT_FINISHED);
3074 return;
3075 }
3076 if pi_raw(ctxt) == b'<'
3077 && pi_nxt(ctxt, 1) == b'!'
3078 && pi_nxt(ctxt, 2) == b'['
3079 {
3080 pi_skip(ctxt, 3);
3081 ignore_depth += 1;
3082 } else if pi_raw(ctxt) == b']'
3083 && pi_nxt(ctxt, 1) == b']'
3084 && pi_nxt(ctxt, 2) == b'>'
3085 {
3086 pi_skip(ctxt, 3);
3087 if ignore_depth == 0 {
3088 break;
3089 }
3090 ignore_depth -= 1;
3091 } else {
3092 pi_next1(ctxt);
3093 }
3094 }
3095 } else {
3096 pi_fatal_err(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD);
3097 return;
3098 }
3099 } else if depth > 0
3100 && pi_raw(ctxt) == b']'
3101 && pi_nxt(ctxt, 1) == b']'
3102 && pi_nxt(ctxt, 2) == b'>'
3103 {
3104 depth -= 1;
3105 pi_skip(ctxt, 3);
3106 } else if pi_raw(ctxt) == b'<' && (pi_nxt(ctxt, 1) == b'!' || pi_nxt(ctxt, 1) == b'?') {
3107 pi_parse_markup_decl(ctxt);
3108 } else if pi_raw(ctxt) == b'%' {
3109 pi_parse_pe_reference(ctxt);
3110 } else {
3111 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3112 return;
3113 }
3114 if depth == 0 {
3115 break;
3116 }
3117 pi_skip_blanks(ctxt);
3118 }
3119 }
3120}
3121
3122unsafe fn pi_parse_version_num(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
3124 unsafe {
3125 let mut buf: Vec<u8> = Vec::new();
3126 let mut cur = pi_raw(ctxt);
3127 if !cur.is_ascii_digit() {
3128 return ptr::null_mut();
3129 }
3130 buf.push(cur);
3131 pi_next1(ctxt);
3132 cur = pi_raw(ctxt);
3133 if cur != b'.' {
3134 return ptr::null_mut();
3135 }
3136 buf.push(cur);
3137 pi_next1(ctxt);
3138 cur = pi_raw(ctxt);
3139 while cur.is_ascii_digit() {
3140 buf.push(cur);
3141 pi_next1(ctxt);
3142 cur = pi_raw(ctxt);
3143 }
3144 pi_strndup_bytes(buf.as_ptr(), buf.len())
3145 }
3146}
3147
3148unsafe fn pi_parse_version_info(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
3150 unsafe {
3151 if pi_cmp7(ctxt, b"version") {
3152 pi_skip(ctxt, 7);
3153 pi_skip_blanks(ctxt);
3154 if pi_raw(ctxt) != b'=' {
3155 pi_fatal_err(ctxt, XML_ERR_EQUAL_REQUIRED);
3156 return ptr::null_mut();
3157 }
3158 pi_next1(ctxt);
3159 pi_skip_blanks(ctxt);
3160 if pi_raw(ctxt) == b'"' {
3161 pi_next1(ctxt);
3162 let version = pi_parse_version_num(ctxt);
3163 if pi_raw(ctxt) != b'"' {
3164 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3165 } else {
3166 pi_next1(ctxt);
3167 }
3168 return version;
3169 } else if pi_raw(ctxt) == b'\'' {
3170 pi_next1(ctxt);
3171 let version = pi_parse_version_num(ctxt);
3172 if pi_raw(ctxt) != b'\'' {
3173 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3174 } else {
3175 pi_next1(ctxt);
3176 }
3177 return version;
3178 } else {
3179 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
3180 }
3181 }
3182 ptr::null_mut()
3183 }
3184}
3185
3186unsafe fn pi_parse_enc_name(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
3188 unsafe {
3189 let cur = pi_raw(ctxt);
3190 if !(cur.is_ascii_lowercase() || cur.is_ascii_uppercase()) {
3191 pi_fatal_err(ctxt, XML_ERR_ENCODING_NAME);
3192 return ptr::null_mut();
3193 }
3194 let mut buf: Vec<u8> = Vec::new();
3195 buf.push(cur);
3196 pi_next1(ctxt);
3197 let mut c = pi_raw(ctxt);
3198 while c.is_ascii_alphanumeric() || c == b'.' || c == b'_' || c == b'-' {
3199 buf.push(c);
3200 pi_next1(ctxt);
3201 c = pi_raw(ctxt);
3202 }
3203 pi_strndup_bytes(buf.as_ptr(), buf.len())
3204 }
3205}
3206
3207unsafe fn pi_parse_encoding_decl(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
3209 unsafe {
3210 pi_skip_blanks(ctxt);
3211 if !pi_cmp8(ctxt, b"encoding") {
3212 return ptr::null();
3213 }
3214 pi_skip(ctxt, 8);
3215 pi_skip_blanks(ctxt);
3216 if pi_raw(ctxt) != b'=' {
3217 pi_fatal_err(ctxt, XML_ERR_EQUAL_REQUIRED);
3218 return ptr::null();
3219 }
3220 pi_next1(ctxt);
3221 pi_skip_blanks(ctxt);
3222 let mut encoding: *mut xmlChar = ptr::null_mut();
3223 if pi_raw(ctxt) == b'"' {
3224 pi_next1(ctxt);
3225 encoding = pi_parse_enc_name(ctxt);
3226 if pi_raw(ctxt) != b'"' {
3227 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3228 if !encoding.is_null() {
3229 xmlFreeImpl(encoding as *mut c_void);
3230 }
3231 return ptr::null();
3232 }
3233 pi_next1(ctxt);
3234 } else if pi_raw(ctxt) == b'\'' {
3235 pi_next1(ctxt);
3236 encoding = pi_parse_enc_name(ctxt);
3237 if pi_raw(ctxt) != b'\'' {
3238 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3239 if !encoding.is_null() {
3240 xmlFreeImpl(encoding as *mut c_void);
3241 }
3242 return ptr::null();
3243 }
3244 pi_next1(ctxt);
3245 } else {
3246 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
3247 }
3248 if encoding.is_null() {
3249 return ptr::null();
3250 }
3251 let c = &mut *ctxt;
3252 if !c.encoding.is_null() {
3253 xmlFreeImpl(c.encoding as *mut c_void);
3254 }
3255 c.encoding = encoding;
3256 c.encoding as *const xmlChar
3257 }
3258}
3259
3260unsafe fn pi_parse_sd_decl(ctxt: *mut _xmlParserCtxt) -> c_int {
3262 unsafe {
3263 let mut standalone = -2;
3264 pi_skip_blanks(ctxt);
3265 if pi_cmp10(ctxt, b"standalone") {
3266 pi_skip(ctxt, 10);
3267 pi_skip_blanks(ctxt);
3268 if pi_raw(ctxt) != b'=' {
3269 pi_fatal_err(ctxt, XML_ERR_EQUAL_REQUIRED);
3270 return standalone;
3271 }
3272 pi_next1(ctxt);
3273 pi_skip_blanks(ctxt);
3274 let quote = pi_raw(ctxt);
3275 if quote == b'\'' || quote == b'"' {
3276 pi_next1(ctxt);
3277 if pi_raw(ctxt) == b'n' && pi_nxt(ctxt, 1) == b'o' {
3278 standalone = 0;
3279 pi_skip(ctxt, 2);
3280 } else if pi_raw(ctxt) == b'y' && pi_nxt(ctxt, 1) == b'e' && pi_nxt(ctxt, 2) == b's' {
3281 standalone = 1;
3282 pi_skip(ctxt, 3);
3283 } else {
3284 pi_fatal_err(ctxt, XML_ERR_STANDALONE_VALUE);
3285 }
3286 if pi_raw(ctxt) != quote {
3287 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3288 } else {
3289 pi_next1(ctxt);
3290 }
3291 } else {
3292 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
3293 }
3294 }
3295 standalone
3296 }
3297}
3298
3299unsafe fn pi_parse_xml_decl(ctxt: *mut _xmlParserCtxt) {
3301 unsafe {
3302 (*ctxt).standalone = -2;
3303 pi_skip(ctxt, 5);
3304 if !pi_is_blank_ch(pi_raw(ctxt)) {
3305 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3306 }
3307 pi_skip_blanks(ctxt);
3308 let version = pi_parse_version_info(ctxt);
3309 if version.is_null() {
3310 pi_fatal_err(ctxt, XML_ERR_VERSION_MISSING);
3311 } else {
3312 if !pi_cstr_eq(version, b"1.0") {
3313 if pi_nxt(ctxt, 0) == b'1' {
3314 } else {
3316 pi_fatal_err(ctxt, XML_ERR_UNKNOWN_VERSION);
3317 }
3318 }
3319 let c = &mut *ctxt;
3320 if !c.version.is_null() {
3321 xmlFreeImpl(c.version as *mut c_void);
3322 }
3323 c.version = version;
3324 }
3325 if !pi_is_blank_ch(pi_raw(ctxt)) {
3326 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3327 pi_skip(ctxt, 2);
3328 return;
3329 }
3330 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3331 }
3332 pi_parse_encoding_decl(ctxt);
3333 if !(*ctxt).encoding.is_null() && !pi_is_blank_ch(pi_raw(ctxt)) {
3334 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3335 pi_skip(ctxt, 2);
3336 return;
3337 }
3338 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3339 }
3340 pi_skip_blanks(ctxt);
3341 (*ctxt).standalone = pi_parse_sd_decl(ctxt);
3342 pi_skip_blanks(ctxt);
3343 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3344 pi_skip(ctxt, 2);
3345 } else if pi_raw(ctxt) == b'>' {
3346 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
3347 pi_next1(ctxt);
3348 } else {
3349 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
3350 while !pi_stopped(ctxt) && pi_raw(ctxt) != 0 {
3351 let c = pi_raw(ctxt);
3352 pi_next1(ctxt);
3353 if c == b'>' {
3354 break;
3355 }
3356 }
3357 }
3358 }
3359}
3360
3361unsafe fn pi_parse_misc(ctxt: *mut _xmlParserCtxt) {
3363 unsafe {
3364 while !pi_stopped(ctxt) {
3365 pi_skip_blanks(ctxt);
3366 if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'?' {
3367 pi_parse_pi(ctxt);
3368 } else if pi_raw(ctxt) == b'<'
3369 && pi_nxt(ctxt, 1) == b'!'
3370 && pi_nxt(ctxt, 2) == b'-'
3371 && pi_nxt(ctxt, 3) == b'-'
3372 {
3373 pi_parse_comment(ctxt);
3374 } else {
3375 break;
3376 }
3377 }
3378 }
3379}
3380
3381unsafe fn pi_parse_content(ctxt: *mut _xmlParserCtxt) {
3383 unsafe {
3384 if ctxt.is_null() || pi_input(ctxt).is_null() {
3385 return;
3386 }
3387 pi_ctxt_late_init(ctxt);
3388 let old_name_nr = (*ctxt).nameNr;
3389 let old_space_nr = (*ctxt).spaceNr;
3390 let old_node_nr = (*ctxt).nodeNr;
3391 loop {
3392 let input = pi_input(ctxt);
3393 if input.is_null() {
3394 break;
3395 }
3396 if (*input).cur >= (*input).end || pi_stopped(ctxt) {
3397 break;
3398 }
3399 let cur = (*input).cur;
3400 if *cur == b'<' {
3401 if cur.add(1) < (*input).end && *cur.add(1) == b'?' {
3402 pi_parse_pi(ctxt);
3403 } else if cur.add(8) < (*input).end
3404 && *cur.add(1) == b'!'
3405 && *cur.add(2) == b'['
3406 && *cur.add(3) == b'C'
3407 && *cur.add(4) == b'D'
3408 && *cur.add(5) == b'A'
3409 && *cur.add(6) == b'T'
3410 && *cur.add(7) == b'A'
3411 && *cur.add(8) == b'['
3412 {
3413 pi_parse_cd_sect(ctxt);
3414 } else if cur.add(3) < (*input).end
3415 && *cur.add(1) == b'!'
3416 && *cur.add(2) == b'-'
3417 && *cur.add(3) == b'-'
3418 {
3419 pi_parse_comment(ctxt);
3420 } else if cur.add(1) < (*input).end && *cur.add(1) == b'/' {
3421 if (*ctxt).nameNr <= old_name_nr {
3422 break;
3423 }
3424 pi_parse_end_tag(ctxt);
3425 } else {
3426 pi_parse_element(ctxt);
3427 }
3428 } else if *cur == b'&' {
3429 pi_parse_reference(ctxt);
3430 } else {
3431 pi_parse_char_data(ctxt, 0);
3432 }
3433 }
3434 if (*ctxt).nameNr > old_name_nr
3436 && pi_input(ctxt).is_null() == false
3437 && (*(*ctxt).input).cur >= (*(*ctxt).input).end
3438 && (*ctxt).wellFormed != 0
3439 {
3440 pi_fatal_err(ctxt, XML_ERR_TAG_NOT_FINISHED);
3441 }
3442 while (*ctxt).nodeNr > old_node_nr {
3444 pi_node_pop(ctxt);
3445 }
3446 while (*ctxt).nameNr > old_name_nr {
3447 pi_name_pop(ctxt);
3448 }
3449 while (*ctxt).spaceNr > old_space_nr {
3450 pi_space_pop(ctxt);
3451 }
3452 }
3453}
3454
3455unsafe fn pi_parse_attribute(ctxt: *mut _xmlParserCtxt, value: *mut *mut xmlChar) -> *const xmlChar {
3457 unsafe {
3458 *value = ptr::null_mut();
3459 let name = pi_parse_name(ctxt);
3460 if name.is_null() {
3461 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
3462 return ptr::null();
3463 }
3464 pi_skip_blanks(ctxt);
3465 let mut val: *mut xmlChar = ptr::null_mut();
3466 if pi_raw(ctxt) == b'=' {
3467 pi_next1(ctxt);
3468 pi_skip_blanks(ctxt);
3469 val = pi_parse_att_value(ctxt);
3470 } else {
3471 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE);
3472 return name;
3473 }
3474 if pi_cstr_eq(name, b"xml:space") && !val.is_null() && !(*ctxt).space.is_null() {
3476 if pi_cstr_eq(val, b"default") {
3477 *(*ctxt).space = 0;
3478 } else if pi_cstr_eq(val, b"preserve") {
3479 *(*ctxt).space = 1;
3480 }
3481 }
3482 *value = val;
3483 name
3484 }
3485}
3486
3487unsafe fn pi_parse_start_tag(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
3489 unsafe {
3490 if pi_raw(ctxt) != b'<' {
3491 return ptr::null();
3492 }
3493 pi_next1(ctxt);
3494 let name = pi_parse_name(ctxt);
3495 if name.is_null() {
3496 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
3497 return ptr::null();
3498 }
3499 let c0 = &mut *ctxt;
3500 let mut atts = c0.atts;
3501 let mut maxatts = c0.maxatts;
3502 let mut nbatts: usize = 0;
3503 let mut failed = false;
3504
3505 pi_skip_blanks(ctxt);
3506 while !(pi_raw(ctxt) == b'>' || (pi_raw(ctxt) == b'/' && pi_nxt(ctxt, 1) == b'>'))
3507 && pi_is_byte_char(pi_raw(ctxt))
3508 && !pi_stopped(ctxt)
3509 {
3510 let mut attvalue: *mut xmlChar = ptr::null_mut();
3511 let attname = pi_parse_attribute(ctxt, &mut attvalue);
3512 if attname.is_null() {
3513 failed = true;
3514 if !attvalue.is_null() {
3515 xmlFreeImpl(attvalue as *mut c_void);
3516 }
3517 break;
3518 }
3519 if !attvalue.is_null() {
3520 let mut i = 0;
3522 while i < nbatts {
3523 if crate::abi::exports_xml2::xmlStrEqual(*atts.add(i), attname) != 0 {
3524 failed = true;
3525 break;
3526 }
3527 i += 2;
3528 }
3529 if failed {
3530 if !attvalue.is_null() {
3531 xmlFreeImpl(attvalue as *mut c_void);
3532 }
3533 break;
3534 }
3535 if nbatts + 4 > maxatts as usize {
3537 let new_max = if maxatts == 0 { 20 } else { maxatts * 2 };
3538 let n = xmlReallocImpl(
3539 atts as *mut c_void,
3540 (new_max as usize) * size_of::<*const xmlChar>(),
3541 ) as *mut *const xmlChar;
3542 if n.is_null() {
3543 pi_err_memory(ctxt);
3544 failed = true;
3545 xmlFreeImpl(attvalue as *mut c_void);
3546 break;
3547 }
3548 atts = n;
3549 maxatts = new_max;
3550 let c = &mut *ctxt;
3551 c.atts = atts;
3552 c.maxatts = maxatts;
3553 }
3554 *atts.add(nbatts) = attname;
3555 *atts.add(nbatts + 1) = attvalue;
3556 nbatts += 2;
3557 attvalue = ptr::null_mut();
3558 } else {
3559 failed = true;
3560 }
3561 if !attvalue.is_null() {
3562 xmlFreeImpl(attvalue as *mut c_void);
3563 }
3564 if pi_raw(ctxt) == b'>' || (pi_raw(ctxt) == b'/' && pi_nxt(ctxt, 1) == b'>') {
3565 break;
3566 }
3567 if pi_skip_blanks(ctxt) == 0 {
3568 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3569 }
3570 }
3571
3572 pi_dispatch_start_element(ctxt, name, atts, nbatts);
3574
3575 let mut i = 0;
3577 while i < nbatts {
3578 if !atts.is_null() {
3579 let p = *atts.add(i);
3580 if !p.is_null() {
3581 xmlFreeImpl(p as *mut c_void);
3582 }
3583 }
3584 i += 1;
3585 }
3586 name
3587 }
3588}
3589
3590unsafe fn pi_parse_end_tag(ctxt: *mut _xmlParserCtxt) {
3592 unsafe {
3593 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'/' {
3594 pi_fatal_err(ctxt, XML_ERR_LTSLASH_REQUIRED);
3595 return;
3596 }
3597 pi_skip(ctxt, 2);
3598 let c = &*ctxt;
3599 let name = pi_parse_name_and_compare(ctxt, c.name);
3600 pi_skip_blanks(ctxt);
3601 if !pi_is_byte_char(pi_raw(ctxt)) || pi_raw(ctxt) != b'>' {
3602 pi_fatal_err(ctxt, XML_ERR_GT_REQUIRED);
3603 } else {
3604 pi_next1(ctxt);
3605 }
3606 if name != 1 as *const xmlChar {
3607 if name.is_null() {
3608 pi_fatal_err(ctxt, XML_ERR_TAG_NAME_MISMATCH);
3610 } else {
3611 pi_fatal_err(ctxt, XML_ERR_TAG_NAME_MISMATCH);
3612 xmlFreeImpl(name as *mut c_void);
3613 }
3614 }
3615 let c = &*ctxt;
3617 pi_dispatch_end_element(ctxt, c.name);
3618 pi_name_pop(ctxt);
3619 pi_space_pop(ctxt);
3620 }
3621}
3622
3623unsafe fn pi_parse_element(ctxt: *mut _xmlParserCtxt) {
3625 unsafe {
3626 let max_depth = if (*ctxt).options & XML_PARSE_HUGE != 0 { 2048 } else { 256 };
3627 if (*ctxt).nameNr > max_depth {
3628 pi_fatal_err(ctxt, XML_ERR_RESOURCE_LIMIT);
3629 return;
3630 }
3631 let c = &mut *ctxt;
3633 if c.spaceNr == 0 {
3634 pi_space_push(ctxt, -1);
3635 } else if !c.space.is_null() && *c.space == -2 {
3636 pi_space_push(ctxt, -1);
3637 } else if !c.space.is_null() {
3638 pi_space_push(ctxt, *c.space);
3639 } else {
3640 pi_space_push(ctxt, -1);
3641 }
3642 let line = (*(*ctxt).input).line;
3643 let name = pi_parse_start_tag(ctxt);
3644 if name.is_null() {
3645 pi_space_pop(ctxt);
3646 return;
3647 }
3648 pi_name_push(ctxt, name);
3649
3650 if pi_raw(ctxt) == b'/' && pi_nxt(ctxt, 1) == b'>' {
3652 pi_skip(ctxt, 2);
3653 let c = &*ctxt;
3654 pi_dispatch_end_element(ctxt, c.name);
3655 pi_name_pop(ctxt);
3656 pi_space_pop(ctxt);
3657 return;
3658 }
3659 if pi_raw(ctxt) == b'>' {
3660 pi_next1(ctxt);
3661 } else {
3662 pi_fatal_err(ctxt, XML_ERR_GT_REQUIRED);
3663 pi_name_pop(ctxt);
3664 pi_space_pop(ctxt);
3665 return;
3666 }
3667
3668 pi_parse_content(ctxt);
3670
3671 let input = pi_input(ctxt);
3673 if input.is_null() || (*input).cur >= (*input).end {
3674 if (*ctxt).wellFormed != 0 {
3675 pi_fatal_err(ctxt, XML_ERR_TAG_NOT_FINISHED);
3676 }
3677 return;
3678 }
3679 pi_parse_end_tag(ctxt);
3680 }
3681}
3682
3683unsafe fn pi_parse_doc_type_decl(ctxt: *mut _xmlParserCtxt) {
3685 unsafe {
3686 pi_skip(ctxt, 9);
3687 if pi_skip_blanks(ctxt) == 0 {
3688 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3689 }
3690 let name = pi_parse_name(ctxt);
3691 if name.is_null() {
3692 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
3693 return;
3694 }
3695 (*ctxt).intSubName = name;
3696 pi_skip_blanks(ctxt);
3697 let mut public_id: *mut xmlChar = ptr::null_mut();
3698 let uri = pi_parse_external_id(ctxt, &mut public_id, 1);
3699 if !uri.is_null() || !public_id.is_null() {
3700 (*ctxt).hasExternalSubset = 1;
3701 }
3702 (*ctxt).extSubURI = uri;
3703 (*ctxt).extSubSystem = public_id;
3704 pi_skip_blanks(ctxt);
3705 let c = &*ctxt;
3706 if !c.sax.is_null() && c.disableSAX == 0 {
3707 SaxDispatcher::internal_subset(&*c.sax, c.userData, name, public_id, uri);
3708 }
3709 if pi_raw(ctxt) != b'[' && pi_raw(ctxt) != b'>' {
3710 pi_fatal_err(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED);
3711 }
3712 }
3713}
3714
3715unsafe fn pi_parse_internal_subset(ctxt: *mut _xmlParserCtxt) {
3717 unsafe {
3718 if pi_raw(ctxt) == b'[' {
3719 let old_input_nr = (*ctxt).inputNr;
3720 pi_next1(ctxt);
3721 pi_skip_blanks(ctxt);
3722 loop {
3723 if pi_stopped(ctxt) {
3724 return;
3725 }
3726 let input = pi_input(ctxt);
3727 if input.is_null() {
3728 return;
3729 }
3730 if (*input).cur >= (*input).end {
3731 if (*ctxt).inputNr <= old_input_nr {
3732 pi_fatal_err(ctxt, XML_ERR_INT_SUBSET_NOT_FINISHED);
3733 return;
3734 }
3735 pi_pop_pe(ctxt);
3736 } else if pi_raw(ctxt) == b']' && (*ctxt).inputNr <= old_input_nr {
3737 pi_next1(ctxt);
3738 pi_skip_blanks(ctxt);
3739 break;
3740 } else if pi_raw(ctxt) == b'<' && (pi_nxt(ctxt, 1) == b'!' || pi_nxt(ctxt, 1) == b'?') {
3741 pi_parse_markup_decl(ctxt);
3742 } else if pi_raw(ctxt) == b'%' {
3743 pi_parse_pe_reference(ctxt);
3744 } else {
3745 pi_fatal_err(ctxt, XML_ERR_INT_SUBSET_NOT_FINISHED);
3746 while (*ctxt).inputNr > old_input_nr {
3747 pi_pop_pe(ctxt);
3748 }
3749 return;
3750 }
3751 pi_skip_blanks(ctxt);
3752 }
3753 }
3754 if pi_raw(ctxt) != b'>' {
3755 pi_fatal_err(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED);
3756 return;
3757 }
3758 pi_next1(ctxt);
3759 }
3760}
3761
3762unsafe fn pi_parse_document(ctxt: *mut _xmlParserCtxt) -> c_int {
3764 unsafe {
3765 if ctxt.is_null() || pi_input(ctxt).is_null() {
3766 return -1;
3767 }
3768 pi_ctxt_late_init(ctxt);
3769
3770 let c0 = &*ctxt;
3772 if !c0.sax.is_null() && (*c0.sax).setDocumentLocator.is_some() {
3773 SaxDispatcher::set_document_locator(
3774 &*c0.sax,
3775 c0.userData,
3776 &crate::abi::data_globals::xmlDefaultSAXLocator as *const _xmlSAXLocator
3777 as *mut _xmlSAXLocator,
3778 );
3779 }
3780
3781 if pi_raw(ctxt) == 0 {
3782 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_EMPTY);
3783 return -1;
3784 }
3785
3786 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
3787 pi_parse_xml_decl(ctxt);
3788 pi_skip_blanks(ctxt);
3789 } else {
3790 let c = &mut *ctxt;
3791 if !c.version.is_null() {
3792 xmlFreeImpl(c.version as *mut c_void);
3793 }
3794 c.version = crate::abi::exports_xml2::xmlStrdup(b"1.0\0".as_ptr() as *const xmlChar);
3795 if c.version.is_null() {
3796 pi_err_memory(ctxt);
3797 return -1;
3798 }
3799 }
3800 let c1 = &*ctxt;
3801 if !c1.sax.is_null() && c1.disableSAX == 0 {
3802 SaxDispatcher::start_document(&*c1.sax, c1.userData);
3803 }
3804
3805 pi_parse_misc(ctxt);
3807
3808 if pi_cmp9(ctxt, b"<!DOCTYPE") {
3810 let c = &mut *ctxt;
3811 c.inSubset = 1;
3812 pi_parse_doc_type_decl(ctxt);
3813 if pi_raw(ctxt) == b'[' {
3814 pi_parse_internal_subset(ctxt);
3815 } else if pi_raw(ctxt) == b'>' {
3816 pi_next1(ctxt);
3817 }
3818 c.inSubset = 2;
3819 let c2 = &*ctxt;
3820 if !c2.sax.is_null() && c2.disableSAX == 0 {
3821 SaxDispatcher::external_subset(
3822 &*c2.sax,
3823 c2.userData,
3824 c2.intSubName,
3825 c2.extSubSystem,
3826 c2.extSubURI,
3827 );
3828 }
3829 let c3 = &mut *ctxt;
3830 c3.inSubset = 0;
3831 pi_parse_misc(ctxt);
3832 }
3833
3834 if pi_raw(ctxt) != b'<' {
3836 if (*ctxt).wellFormed != 0 {
3837 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_EMPTY);
3838 }
3839 } else {
3840 pi_parse_element(ctxt);
3841 pi_parse_misc(ctxt);
3842 if !pi_stopped(ctxt) {
3844 let input = pi_input(ctxt);
3845 if !input.is_null() && (*input).cur < (*input).end {
3846 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_END);
3847 }
3848 }
3849 }
3850
3851 let c = &mut *ctxt;
3852 c.instate = XML_PARSER_EOF_STATE;
3853 if !c.sax.is_null() && c.disableSAX == 0 {
3854 SaxDispatcher::end_document(&*c.sax, c.userData);
3855 }
3856 if c.wellFormed == 0 {
3857 c.valid = 0;
3858 return -1;
3859 }
3860 0
3861 }
3862}
3863
3864unsafe fn pi_parse_ext_parsed_ent(ctxt: *mut _xmlParserCtxt) -> c_int {
3866 unsafe {
3867 if ctxt.is_null() || pi_input(ctxt).is_null() {
3868 return -1;
3869 }
3870 pi_ctxt_late_init(ctxt);
3871 if pi_raw(ctxt) == 0 {
3872 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_EMPTY);
3873 }
3874 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
3875 pi_parse_xml_decl(ctxt);
3876 pi_skip_blanks(ctxt);
3877 } else {
3878 let c = &mut *ctxt;
3879 if !c.version.is_null() {
3880 xmlFreeImpl(c.version as *mut c_void);
3881 }
3882 c.version = crate::abi::exports_xml2::xmlStrdup(b"1.0\0".as_ptr() as *const xmlChar);
3883 }
3884 let c0 = &*ctxt;
3885 if !c0.sax.is_null() && c0.disableSAX == 0 {
3886 SaxDispatcher::start_document(&*c0.sax, c0.userData);
3887 }
3888 let c1 = &mut *ctxt;
3889 c1.options &= !XML_PARSE_DTDVALID;
3890 c1.validate = 0;
3891 c1.depth = 0;
3892
3893 pi_parse_content(ctxt);
3894
3895 let input = pi_input(ctxt);
3896 if !input.is_null() && (*input).cur < (*input).end {
3897 pi_fatal_err(ctxt, XML_ERR_NOT_WELL_BALANCED);
3898 }
3899 let c2 = &*ctxt;
3900 if !c2.sax.is_null() && c2.disableSAX == 0 {
3901 SaxDispatcher::end_document(&*c2.sax, c2.userData);
3902 }
3903 if (*ctxt).wellFormed == 0 {
3904 return -1;
3905 }
3906 0
3907 }
3908}
3909
3910unsafe fn pi_parse_content_node_list(
3913 ctxt: *mut _xmlParserCtxt,
3914 input: *mut _xmlParserInput,
3915 has_text_decl: c_int,
3916) -> *mut _xmlNode {
3917 unsafe {
3918 let mut root: *mut _xmlNode = ptr::null_mut();
3919 let mut list: *mut _xmlNode = ptr::null_mut();
3920 let root_name = b"#root\0";
3921 root = crate::xml::tree::new_node(
3922 ptr::null_mut(),
3923 root_name.as_ptr() as *const xmlChar,
3924 );
3925 if root.is_null() {
3926 pi_err_memory(ctxt);
3927 return ptr::null_mut();
3928 }
3929 if pi_input_push(ctxt, input) < 0 {
3930 crate::xml::tree::free_node(root);
3931 return ptr::null_mut();
3932 }
3933 pi_name_push(ctxt, root_name.as_ptr() as *const xmlChar);
3934 pi_space_push(ctxt, -1);
3935 pi_node_push(ctxt, root);
3936
3937 if has_text_decl != 0
3938 && pi_cmp5(ctxt, b"<?xml")
3939 && pi_is_blank_ch(pi_nxt(ctxt, 5))
3940 {
3941 pi_parse_text_decl(ctxt);
3942 }
3943
3944 pi_parse_content(ctxt);
3945
3946 let cur = pi_input(ctxt);
3947 if !cur.is_null() && (*cur).cur < (*cur).end {
3948 pi_fatal_err(ctxt, XML_ERR_NOT_WELL_BALANCED);
3949 }
3950
3951 if (*ctxt).wellFormed != 0 {
3952 list = (*root).children;
3954 (*root).children = ptr::null_mut();
3955 (*root).last = ptr::null_mut();
3956 let mut n = list;
3957 while !n.is_null() {
3958 (*n).parent = ptr::null_mut();
3959 n = (*n).next;
3960 }
3961 }
3962
3963 if pi_input_pop(ctxt) == input {
3964 }
3966 pi_node_pop(ctxt);
3967 pi_name_pop(ctxt);
3968 pi_space_pop(ctxt);
3969 crate::xml::tree::free_node(root);
3970 list
3971 }
3972}
3973
3974#[no_mangle]
3984pub unsafe extern "C" fn xmlNamespaceParseNCName(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
3985 if ctxt.is_null() || pi_input(ctxt).is_null() {
3986 return ptr::null();
3987 }
3988 unsafe {
3989 let start = pi_cur_ptr(ctxt);
3990 let (c, l) = pi_current_char(ctxt);
3991 if (c != b'_' as c_int && !pi_is_letter_ch(c as u8)) || c == b':' as c_int {
3992 return ptr::null();
3993 }
3994 pi_nextl(ctxt, l);
3995 loop {
3996 let (c2, l2) = pi_current_char(ctxt);
3997 if !pi_is_name_char(c2) || c2 == b':' as c_int {
3998 break;
3999 }
4000 pi_nextl(ctxt, l2);
4001 }
4002 let len = pi_cur_ptr(ctxt).offset_from(start) as usize;
4003 if len == 0 {
4004 return ptr::null();
4005 }
4006 pi_strndup_bytes(start, len)
4007 }
4008}
4009
4010#[no_mangle]
4016pub unsafe extern "C" fn xmlNamespaceParseQName(
4017 ctxt: *mut _xmlParserCtxt,
4018 prefix: *mut *mut xmlChar,
4019) -> *const xmlChar {
4020 if ctxt.is_null() || pi_input(ctxt).is_null() {
4021 return ptr::null();
4022 }
4023 unsafe {
4024 if !prefix.is_null() {
4025 *prefix = ptr::null_mut();
4026 }
4027 let start = pi_cur_ptr(ctxt);
4028 let (c, l) = pi_current_char(ctxt);
4029 if (c != b'_' as c_int && !pi_is_letter_ch(c as u8)) || c == b':' as c_int {
4030 return ptr::null();
4031 }
4032 pi_nextl(ctxt, l);
4033 loop {
4034 let (c2, l2) = pi_current_char(ctxt);
4035 if !pi_is_name_char(c2) || c2 == b':' as c_int {
4036 break;
4037 }
4038 pi_nextl(ctxt, l2);
4039 }
4040 if pi_raw(ctxt) == b':' {
4041 pi_next1(ctxt);
4042 if !prefix.is_null() {
4043 let plen = pi_cur_ptr(ctxt).offset_from(start) as usize - 1;
4044 *prefix = pi_strndup_bytes(start, plen);
4045 }
4046 let lstart = pi_cur_ptr(ctxt);
4047 let (c2, l2) = pi_current_char(ctxt);
4048 if (c2 != b'_' as c_int && !pi_is_letter_ch(c2 as u8)) || c2 == b':' as c_int {
4049 return ptr::null();
4050 }
4051 pi_nextl(ctxt, l2);
4052 loop {
4053 let (c3, l3) = pi_current_char(ctxt);
4054 if !pi_is_name_char(c3) || c3 == b':' as c_int {
4055 break;
4056 }
4057 pi_nextl(ctxt, l3);
4058 }
4059 let llen = pi_cur_ptr(ctxt).offset_from(lstart) as usize;
4060 return pi_strndup_bytes(lstart, llen);
4061 }
4062 let len = pi_cur_ptr(ctxt).offset_from(start) as usize;
4063 if len == 0 {
4064 return ptr::null();
4065 }
4066 pi_strndup_bytes(start, len)
4067 }
4068}
4069
4070#[no_mangle]
4076pub unsafe extern "C" fn xmlNamespaceParseNSDef(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4077 if ctxt.is_null() || pi_input(ctxt).is_null() {
4078 return ptr::null();
4079 }
4080 unsafe {
4081 let start = pi_cur_ptr(ctxt);
4082 if !pi_cmp5(ctxt, b"xmlns") {
4083 return ptr::null();
4084 }
4085 pi_skip(ctxt, 5);
4086 if pi_raw(ctxt) == b':' {
4087 pi_next1(ctxt);
4088 let (c, l) = pi_current_char(ctxt);
4089 if (c != b'_' as c_int && !pi_is_letter_ch(c as u8)) || c == b':' as c_int {
4090 return ptr::null();
4091 }
4092 pi_nextl(ctxt, l);
4093 loop {
4094 let (c2, l2) = pi_current_char(ctxt);
4095 if !pi_is_name_char(c2) || c2 == b':' as c_int {
4096 break;
4097 }
4098 pi_nextl(ctxt, l2);
4099 }
4100 }
4101 let len = pi_cur_ptr(ctxt).offset_from(start) as usize;
4102 pi_strndup_bytes(start, len)
4103 }
4104}
4105
4106#[no_mangle]
4114pub unsafe extern "C" fn xmlParseNamespace(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4115 if ctxt.is_null() || pi_input(ctxt).is_null() {
4116 return ptr::null();
4117 }
4118 unsafe {
4119 let name = xmlNamespaceParseNSDef(ctxt);
4120 if name.is_null() {
4121 return ptr::null();
4122 }
4123 pi_skip_blanks(ctxt);
4124 if pi_raw(ctxt) == b'=' {
4125 pi_next1(ctxt);
4126 pi_skip_blanks(ctxt);
4127 let value = pi_parse_att_value(ctxt);
4128 if value.is_null() {
4129 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE);
4130 return name;
4131 }
4132 xmlFreeImpl(value as *mut c_void);
4133 }
4134 name
4135 }
4136}
4137
4138#[no_mangle]
4144pub unsafe extern "C" fn xmlParseQuotedString(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4145 pi_parse_quoted_string(ctxt)
4146}
4147
4148#[no_mangle]
4154pub unsafe extern "C" fn xmlParseName(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4155 pi_parse_name(ctxt)
4156}
4157
4158#[no_mangle]
4164pub unsafe extern "C" fn xmlParseNmtoken(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4165 pi_parse_nmtoken(ctxt)
4166}
4167
4168#[no_mangle]
4174pub unsafe extern "C" fn xmlParseCharRef(ctxt: *mut _xmlParserCtxt) -> c_int {
4175 pi_parse_char_ref(ctxt)
4176}
4177
4178#[no_mangle]
4184pub unsafe extern "C" fn xmlParseEntityRef(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEntity {
4185 pi_parse_entity_ref(ctxt)
4186}
4187
4188#[no_mangle]
4194pub unsafe extern "C" fn xmlParseEntityValue(
4195 ctxt: *mut _xmlParserCtxt,
4196 orig: *mut *mut xmlChar,
4197) -> *mut xmlChar {
4198 pi_parse_entity_value(ctxt, orig)
4199}
4200
4201#[no_mangle]
4207pub unsafe extern "C" fn xmlParseAttValue(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4208 pi_parse_att_value(ctxt)
4209}
4210
4211#[no_mangle]
4217pub unsafe extern "C" fn xmlParseSystemLiteral(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4218 pi_parse_system_literal(ctxt)
4219}
4220
4221#[no_mangle]
4227pub unsafe extern "C" fn xmlParsePubidLiteral(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4228 pi_parse_pubid_literal(ctxt)
4229}
4230
4231#[no_mangle]
4237pub unsafe extern "C" fn xmlParseExternalID(
4238 ctxt: *mut _xmlParserCtxt,
4239 public_id: *mut *mut xmlChar,
4240 strict: c_int,
4241) -> *mut xmlChar {
4242 if ctxt.is_null() || public_id.is_null() {
4243 return ptr::null_mut();
4244 }
4245 pi_parse_external_id(ctxt, public_id, strict)
4246}
4247
4248#[no_mangle]
4254pub unsafe extern "C" fn xmlParsePITarget(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4255 pi_parse_pi_target(ctxt)
4256}
4257
4258#[no_mangle]
4264pub unsafe extern "C" fn xmlParsePI(ctxt: *mut _xmlParserCtxt) {
4265 pi_parse_pi(ctxt)
4266}
4267
4268#[no_mangle]
4274pub unsafe extern "C" fn xmlParseComment(ctxt: *mut _xmlParserCtxt) {
4275 pi_parse_comment(ctxt)
4276}
4277
4278#[no_mangle]
4284pub unsafe extern "C" fn xmlParseCharData(ctxt: *mut _xmlParserCtxt, cdata: c_int) {
4285 pi_parse_char_data(ctxt, cdata)
4286}
4287
4288#[no_mangle]
4294pub unsafe extern "C" fn xmlParseCDSect(ctxt: *mut _xmlParserCtxt) {
4295 pi_parse_cd_sect(ctxt)
4296}
4297
4298#[no_mangle]
4304pub unsafe extern "C" fn xmlParseReference(ctxt: *mut _xmlParserCtxt) {
4305 pi_parse_reference(ctxt)
4306}
4307
4308#[no_mangle]
4314pub unsafe extern "C" fn xmlParserHandleReference(ctxt: *mut _xmlParserCtxt) {
4315 pi_parse_reference(ctxt)
4316}
4317
4318#[no_mangle]
4324pub unsafe extern "C" fn xmlParsePEReference(ctxt: *mut _xmlParserCtxt) {
4325 pi_parse_pe_reference(ctxt)
4326}
4327
4328#[no_mangle]
4334pub unsafe extern "C" fn xmlParserHandlePEReference(ctxt: *mut _xmlParserCtxt) {
4335 pi_parse_pe_reference(ctxt)
4336}
4337
4338#[no_mangle]
4344pub unsafe extern "C" fn xmlParseNotationDecl(ctxt: *mut _xmlParserCtxt) {
4345 pi_parse_notation_decl(ctxt)
4346}
4347
4348#[no_mangle]
4354pub unsafe extern "C" fn xmlParseEntityDecl(ctxt: *mut _xmlParserCtxt) {
4355 pi_parse_entity_decl(ctxt)
4356}
4357
4358#[no_mangle]
4364pub unsafe extern "C" fn xmlParseDefaultDecl(
4365 ctxt: *mut _xmlParserCtxt,
4366 value: *mut *mut xmlChar,
4367) -> c_int {
4368 if ctxt.is_null() || value.is_null() {
4369 return 0;
4370 }
4371 pi_parse_default_decl(ctxt, value)
4372}
4373
4374#[no_mangle]
4380pub unsafe extern "C" fn xmlParseAttributeType(
4381 ctxt: *mut _xmlParserCtxt,
4382 tree: *mut *mut _xmlEnumeration,
4383) -> c_int {
4384 if ctxt.is_null() || tree.is_null() {
4385 return 0;
4386 }
4387 pi_parse_attribute_type(ctxt, tree)
4388}
4389
4390#[no_mangle]
4396pub unsafe extern "C" fn xmlParseNotationType(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
4397 pi_parse_notation_type(ctxt)
4398}
4399
4400#[no_mangle]
4406pub unsafe extern "C" fn xmlParseEnumerationType(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
4407 pi_parse_enumeration_type(ctxt)
4408}
4409
4410#[no_mangle]
4416pub unsafe extern "C" fn xmlParseEnumeratedType(
4417 ctxt: *mut _xmlParserCtxt,
4418 tree: *mut *mut _xmlEnumeration,
4419) -> c_int {
4420 if ctxt.is_null() || tree.is_null() {
4421 return 0;
4422 }
4423 pi_parse_enumerated_type(ctxt, tree)
4424}
4425
4426#[no_mangle]
4432pub unsafe extern "C" fn xmlParseAttributeListDecl(ctxt: *mut _xmlParserCtxt) {
4433 pi_parse_attribute_list_decl(ctxt)
4434}
4435
4436#[no_mangle]
4442pub unsafe extern "C" fn xmlParseElementMixedContentDecl(
4443 ctxt: *mut _xmlParserCtxt,
4444 inputchk: c_int,
4445) -> *mut _xmlElementContent {
4446 pi_parse_element_mixed_content_decl(ctxt, inputchk)
4447}
4448
4449#[no_mangle]
4455pub unsafe extern "C" fn xmlParseElementChildrenContentDecl(
4456 ctxt: *mut _xmlParserCtxt,
4457 inputchk: c_int,
4458) -> *mut _xmlElementContent {
4459 pi_parse_element_children_content_decl_priv(ctxt, inputchk, 1)
4460}
4461
4462#[no_mangle]
4469pub unsafe extern "C" fn xmlParseElementContentDecl(
4470 ctxt: *mut _xmlParserCtxt,
4471 name: *const xmlChar,
4472 result: *mut *mut _xmlElementContent,
4473) -> c_int {
4474 if ctxt.is_null() || result.is_null() {
4475 return -1;
4476 }
4477 pi_parse_element_content_decl(ctxt, name, result)
4478}
4479
4480#[no_mangle]
4486pub unsafe extern "C" fn xmlParseElementDecl(ctxt: *mut _xmlParserCtxt) -> c_int {
4487 pi_parse_element_decl(ctxt)
4488}
4489
4490#[no_mangle]
4496pub unsafe extern "C" fn xmlParseMarkupDecl(ctxt: *mut _xmlParserCtxt) {
4497 pi_parse_markup_decl(ctxt)
4498}
4499
4500#[no_mangle]
4506pub unsafe extern "C" fn xmlParseVersionNum(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4507 pi_parse_version_num(ctxt)
4508}
4509
4510#[no_mangle]
4516pub unsafe extern "C" fn xmlParseVersionInfo(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4517 pi_parse_version_info(ctxt)
4518}
4519
4520#[no_mangle]
4526pub unsafe extern "C" fn xmlParseEncName(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4527 pi_parse_enc_name(ctxt)
4528}
4529
4530#[no_mangle]
4536pub unsafe extern "C" fn xmlParseEncodingDecl(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4537 pi_parse_encoding_decl(ctxt)
4538}
4539
4540#[no_mangle]
4546pub unsafe extern "C" fn xmlParseSDDecl(ctxt: *mut _xmlParserCtxt) -> c_int {
4547 pi_parse_sd_decl(ctxt)
4548}
4549
4550#[no_mangle]
4556pub unsafe extern "C" fn xmlParseXMLDecl(ctxt: *mut _xmlParserCtxt) {
4557 pi_parse_xml_decl(ctxt)
4558}
4559
4560#[no_mangle]
4566pub unsafe extern "C" fn xmlParseTextDecl(ctxt: *mut _xmlParserCtxt) {
4567 pi_parse_text_decl(ctxt)
4568}
4569
4570#[no_mangle]
4577pub unsafe extern "C" fn xmlParseExternalSubset(
4578 ctxt: *mut _xmlParserCtxt,
4579 public_id: *const xmlChar,
4580 system_id: *const xmlChar,
4581) {
4582 pi_parse_external_subset(ctxt, public_id, system_id)
4583}
4584
4585#[no_mangle]
4591pub unsafe extern "C" fn xmlParseDocTypeDecl(ctxt: *mut _xmlParserCtxt) {
4592 pi_parse_doc_type_decl(ctxt)
4593}
4594
4595#[no_mangle]
4601pub unsafe extern "C" fn xmlParseAttribute(
4602 ctxt: *mut _xmlParserCtxt,
4603 value: *mut *mut xmlChar,
4604) -> *const xmlChar {
4605 if ctxt.is_null() || value.is_null() {
4606 return ptr::null();
4607 }
4608 pi_parse_attribute(ctxt, value)
4609}
4610
4611#[no_mangle]
4617pub unsafe extern "C" fn xmlParseStartTag(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4618 pi_parse_start_tag(ctxt)
4619}
4620
4621#[no_mangle]
4627pub unsafe extern "C" fn xmlParseEndTag(ctxt: *mut _xmlParserCtxt) {
4628 pi_parse_end_tag(ctxt)
4629}
4630
4631#[no_mangle]
4637pub unsafe extern "C" fn xmlParseElement(ctxt: *mut _xmlParserCtxt) {
4638 pi_parse_element(ctxt)
4639}
4640
4641#[no_mangle]
4647pub unsafe extern "C" fn xmlParseContent(ctxt: *mut _xmlParserCtxt) {
4648 pi_parse_content(ctxt)
4649}
4650
4651#[no_mangle]
4657pub unsafe extern "C" fn xmlParseMisc(ctxt: *mut _xmlParserCtxt) {
4658 pi_parse_misc(ctxt)
4659}
4660
4661#[no_mangle]
4672pub unsafe extern "C" fn xmlParseCtxtExternalEntity(
4673 ctxt: *mut _xmlParserCtxt,
4674 url: *const xmlChar,
4675 _id: *const xmlChar,
4676 list_out: *mut *mut _xmlNode,
4677) -> c_int {
4678 unsafe {
4679 if !list_out.is_null() {
4680 *list_out = ptr::null_mut();
4681 }
4682 if ctxt.is_null() {
4683 return XML_ERR_ARGUMENT;
4684 }
4685 if url.is_null() {
4686 pi_fatal_err(ctxt, XML_ERR_INTERNAL_ERROR);
4687 return (*ctxt).errNo;
4688 }
4689 let url_cstr = url as *const c_char;
4691 let input_buf = match input_from_file(url_cstr) {
4692 Ok(b) => b,
4693 Err(_) => {
4694 pi_fatal_err(ctxt, XML_ERR_INTERNAL_ERROR);
4695 return (*ctxt).errNo;
4696 }
4697 };
4698 let input = {
4699 let boxed = Box::into_raw(Box::new(input_buf));
4702 let pi = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
4703 if pi.is_null() {
4704 let _ = Box::from_raw(boxed);
4705 pi_err_memory(ctxt);
4706 return (*ctxt).errNo;
4707 }
4708 (*boxed).populate_parser_input(&mut *pi);
4709 (*pi).buf = ptr::null_mut();
4710 (*pi).directory = ptr::null();
4711 (*pi).free = None;
4712 (*pi).encoding = ptr::null();
4713 (*pi).version = ptr::null();
4714 (*pi).flags = 0;
4715 (*pi).id = 0;
4716 (*pi).parentConsumed = 0;
4717 (*pi).entity = ptr::null_mut();
4718 (*ctxt)._private = boxed as *mut c_void;
4720 pi
4721 };
4722
4723 pi_ctxt_late_init(ctxt);
4724 let list = pi_parse_content_node_list(ctxt, input, 1);
4725 if !list_out.is_null() {
4726 *list_out = list;
4727 } else if !list.is_null() {
4728 crate::xml::tree::free_node_list(list);
4729 }
4730 (*ctxt).errNo
4731 }
4732}
4733
4734#[no_mangle]
4742pub unsafe extern "C" fn xmlParseExternalEntity(
4743 doc: *mut _xmlDoc,
4744 sax: *mut _xmlSAXHandler,
4745 user_data: *mut c_void,
4746 depth: c_int,
4747 url: *const xmlChar,
4748 id: *const xmlChar,
4749 list: *mut *mut _xmlNode,
4750) -> c_int {
4751 unsafe {
4752 if !list.is_null() {
4753 *list = ptr::null_mut();
4754 }
4755 if doc.is_null() {
4756 return XML_ERR_ARGUMENT;
4757 }
4758 let ctxt = create_parser_ctxt();
4759 if ctxt.is_null() {
4760 return XML_ERR_NO_MEMORY;
4761 }
4762 if !sax.is_null() {
4764 let dst = (*ctxt).sax;
4765 if !dst.is_null() {
4766 ptr::copy_nonoverlapping(sax, dst, 1);
4768 }
4769 (*ctxt).userData = user_data;
4770 }
4771 (*ctxt).depth = depth;
4772 (*ctxt).myDoc = doc;
4773 let ret = xmlParseCtxtExternalEntity(ctxt, url, id, list);
4774 free_parser_ctxt(ctxt);
4775 ret
4776 }
4777}
4778
4779#[no_mangle]
4786pub unsafe extern "C" fn xmlParseBalancedChunkMemory(
4787 doc: *mut _xmlDoc,
4788 sax: *mut _xmlSAXHandler,
4789 user_data: *mut c_void,
4790 depth: c_int,
4791 string: *const xmlChar,
4792 lst: *mut *mut _xmlNode,
4793) -> c_int {
4794 xmlParseBalancedChunkMemoryRecover(doc, sax, user_data, depth, string, lst, 0)
4795}
4796
4797#[no_mangle]
4806pub unsafe extern "C" fn xmlParseBalancedChunkMemoryRecover(
4807 doc: *mut _xmlDoc,
4808 sax: *mut _xmlSAXHandler,
4809 user_data: *mut c_void,
4810 depth: c_int,
4811 string: *const xmlChar,
4812 list_out: *mut *mut _xmlNode,
4813 recover: c_int,
4814) -> c_int {
4815 unsafe {
4816 if !list_out.is_null() {
4817 *list_out = ptr::null_mut();
4818 }
4819 if string.is_null() {
4820 return XML_ERR_ARGUMENT;
4821 }
4822 if doc.is_null() {
4823 return XML_ERR_ARGUMENT;
4824 }
4825 let ctxt = create_parser_ctxt();
4826 if ctxt.is_null() {
4827 return XML_ERR_NO_MEMORY;
4828 }
4829 if !sax.is_null() {
4830 let dst = (*ctxt).sax;
4831 if !dst.is_null() {
4832 ptr::copy_nonoverlapping(sax, dst, 1);
4833 }
4834 (*ctxt).userData = user_data;
4835 }
4836 pi_ctxt_late_init(ctxt);
4837 (*ctxt).depth = depth;
4838 (*ctxt).myDoc = doc;
4839 if recover != 0 {
4840 (*ctxt).options |= XML_PARSE_RECOVER;
4841 (*ctxt).recovery = 1;
4842 }
4843
4844 let slen = crate::abi::exports_xml2::xmlStrlen(string) as c_int;
4845 let input_buf = input_from_memory(string as *const c_char, slen);
4846 let boxed = Box::into_raw(Box::new(input_buf));
4848 (*ctxt)._private = boxed as *mut c_void;
4849 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
4850 if input.is_null() {
4851 let _ = Box::from_raw(boxed);
4852 (*ctxt)._private = ptr::null_mut();
4853 let ret = (*ctxt).errNo;
4854 free_parser_ctxt(ctxt);
4855 return if ret != 0 { ret } else { XML_ERR_NO_MEMORY };
4856 }
4857 (*boxed).populate_parser_input(&mut *input);
4858 (*input).buf = ptr::null_mut();
4859 (*input).directory = ptr::null();
4860 (*input).free = None;
4861 (*input).encoding = ptr::null();
4862 (*input).version = ptr::null();
4863 (*input).flags = 0;
4864 (*input).id = 0;
4865 (*input).parentConsumed = 0;
4866 (*input).entity = ptr::null_mut();
4867
4868 let list = pi_parse_content_node_list(ctxt, input, 0);
4869 if !list_out.is_null() {
4870 *list_out = list;
4871 } else if !list.is_null() {
4872 crate::xml::tree::free_node_list(list);
4873 }
4874 let ret = if (*ctxt).wellFormed == 0 {
4875 (*ctxt).errNo
4876 } else {
4877 XML_ERR_OK
4878 };
4879 free_parser_ctxt(ctxt);
4880 ret
4881 }
4882}
4883
4884#[no_mangle]
4891pub unsafe extern "C" fn xmlParseInNodeContext(
4892 node: *mut _xmlNode,
4893 data: *const c_char,
4894 datalen: c_int,
4895 options: c_int,
4896 list_out: *mut *mut _xmlNode,
4897) -> c_int {
4898 unsafe {
4899 if list_out.is_null() {
4900 return XML_ERR_INTERNAL_ERROR;
4901 }
4902 *list_out = ptr::null_mut();
4903 if node.is_null() || data.is_null() || datalen < 0 {
4904 return XML_ERR_INTERNAL_ERROR;
4905 }
4906 let doc = (*node).doc;
4907 if doc.is_null() {
4908 return XML_ERR_INTERNAL_ERROR;
4909 }
4910 let ctxt = create_parser_ctxt();
4911 if ctxt.is_null() {
4912 return XML_ERR_NO_MEMORY;
4913 }
4914 (*ctxt).options = options;
4915
4916 let input_buf = input_from_memory(data, datalen);
4917 let boxed = Box::into_raw(Box::new(input_buf));
4918 (*ctxt)._private = boxed as *mut c_void;
4919 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
4920 if input.is_null() {
4921 let _ = Box::from_raw(boxed);
4922 (*ctxt)._private = ptr::null_mut();
4923 free_parser_ctxt(ctxt);
4924 return XML_ERR_NO_MEMORY;
4925 }
4926 (*boxed).populate_parser_input(&mut *input);
4927 (*input).buf = ptr::null_mut();
4928 (*input).directory = ptr::null();
4929 (*input).free = None;
4930 (*input).encoding = ptr::null();
4931 (*input).version = ptr::null();
4932 (*input).flags = 0;
4933 (*input).id = 0;
4934 (*input).parentConsumed = 0;
4935 (*input).entity = ptr::null_mut();
4936
4937 pi_ctxt_late_init(ctxt);
4938 (*ctxt).myDoc = doc;
4939
4940 let mut ns_cur = (*node).nsDef;
4943 while !ns_cur.is_null() {
4944 let nsp = ns_cur;
4945 ns_cur = (*ns_cur).next;
4946 if !(*nsp).prefix.is_null() {
4949 }
4951 }
4952
4953 let list = pi_parse_content_node_list(ctxt, input, 0);
4954 if list.is_null() {
4955 let ret = (*ctxt).errNo;
4956 if ret == XML_ERR_ARGUMENT {
4957 free_parser_ctxt(ctxt);
4958 return XML_ERR_INTERNAL_ERROR;
4959 }
4960 free_parser_ctxt(ctxt);
4961 return if ret != 0 { ret } else { XML_ERR_INTERNAL_ERROR };
4962 }
4963 *list_out = list;
4964 free_parser_ctxt(ctxt);
4965 XML_ERR_OK
4966 }
4967}
4968
4969#[no_mangle]
4975pub unsafe extern "C" fn xmlParseDTD(
4976 public_id: *const xmlChar,
4977 system_id: *const xmlChar,
4978) -> *mut _xmlDtd {
4979 unsafe {
4980 if public_id.is_null() && system_id.is_null() {
4981 return ptr::null_mut();
4982 }
4983 if system_id.is_null() {
4984 return ptr::null_mut();
4985 }
4986 let ctxt = create_parser_ctxt();
4987 if ctxt.is_null() {
4988 return ptr::null_mut();
4989 }
4990 pi_ctxt_late_init(ctxt);
4991 (*ctxt).inSubset = 2;
4992 (*ctxt).hasExternalSubset = 1;
4993
4994 let mut ret: *mut _xmlDtd = ptr::null_mut();
4995 let input_buf = input_from_file(system_id as *const c_char);
4996 if let Ok(buf) = input_buf {
4997 let boxed = Box::into_raw(Box::new(buf));
4998 (*ctxt)._private = boxed as *mut c_void;
4999 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
5000 if !input.is_null() {
5001 (*boxed).populate_parser_input(&mut *input);
5002 (*input).buf = ptr::null_mut();
5003 (*input).directory = ptr::null();
5004 (*input).free = None;
5005 (*input).encoding = ptr::null();
5006 (*input).version = ptr::null();
5007 (*input).flags = 0;
5008 (*input).id = 0;
5009 (*input).parentConsumed = 0;
5010 (*input).entity = ptr::null_mut();
5011 (*ctxt).input = input;
5013 (*ctxt).inputNr = 1;
5014 let tab = xmlMallocZero(4 * size_of::<*mut _xmlParserInput>())
5015 as *mut *mut _xmlParserInput;
5016 if !tab.is_null() {
5017 *tab = input;
5018 (*ctxt).inputTab = tab;
5019 (*ctxt).inputMax = 4;
5020 }
5021 pi_parse_external_subset(ctxt, public_id, system_id);
5022 }
5023 }
5024
5025 if (*ctxt).wellFormed != 0 && !(*ctxt).myDoc.is_null() {
5026 let doc = (*ctxt).myDoc;
5027 if !(*doc).intSubset.is_null() {
5028 ret = (*doc).intSubset;
5029 } else if !(*doc).extSubset.is_null() {
5030 ret = (*doc).extSubset;
5031 }
5032 }
5033 free_parser_ctxt(ctxt);
5034 ret
5035 }
5036}
5037
5038#[no_mangle]
5044pub unsafe extern "C" fn xmlParseEntity(filename: *const c_char) -> *mut _xmlDoc {
5045 unsafe {
5046 if filename.is_null() {
5047 return ptr::null_mut();
5048 }
5049 let ctxt = create_parser_ctxt();
5050 if ctxt.is_null() {
5051 return ptr::null_mut();
5052 }
5053 let input_buf = match input_from_file(filename) {
5054 Ok(b) => b,
5055 Err(_) => {
5056 free_parser_ctxt(ctxt);
5057 return ptr::null_mut();
5058 }
5059 };
5060 setup_parser_input(ctxt, input_buf);
5061 xmlParseExtParsedEnt(ctxt);
5062 let ret = if (*ctxt).wellFormed != 0 {
5063 (*ctxt).myDoc
5064 } else {
5065 let doc = (*ctxt).myDoc;
5066 if !doc.is_null() {
5067 crate::xml::tree::free_doc(doc);
5068 (*ctxt).myDoc = ptr::null_mut();
5069 }
5070 ptr::null_mut()
5071 };
5072 (*ctxt).myDoc = ptr::null_mut();
5074 free_parser_ctxt(ctxt);
5075 ret
5076 }
5077}
5078
5079#[no_mangle]
5085pub unsafe extern "C" fn xmlParseExtParsedEnt(ctxt: *mut _xmlParserCtxt) -> c_int {
5086 pi_parse_ext_parsed_ent(ctxt)
5087}
5088
5089#[repr(C)]
5111struct PiInputMem {
5112 data: *mut u8,
5113 len: usize,
5114 cap: usize,
5115 owned: bool,
5116}
5117
5118unsafe fn pi_mem_create() -> *mut PiInputMem {
5119 unsafe { xmlMallocZero(size_of::<PiInputMem>()) as *mut PiInputMem }
5120}
5121
5122unsafe fn pi_mem_free(m: *mut PiInputMem) {
5123 unsafe {
5124 if m.is_null() {
5125 return;
5126 }
5127 if !(*m).data.is_null() && (*m).owned {
5128 xmlFreeImpl((*m).data as *mut c_void);
5129 }
5130 xmlFreeImpl(m as *mut c_void);
5131 }
5132}
5133
5134unsafe fn pi_mem_grow(m: *mut PiInputMem, extra: usize) -> bool {
5135 unsafe {
5136 if m.is_null() {
5137 return false;
5138 }
5139 if (*m).len + extra <= (*m).cap {
5140 return true;
5141 }
5142 let mut new_cap = if (*m).cap == 0 { 256 } else { (*m).cap };
5143 while new_cap < (*m).len + extra {
5144 new_cap *= 2;
5145 }
5146 if !(*m).owned {
5147 let data = xmlMallocImpl(new_cap) as *mut u8;
5149 if data.is_null() {
5150 return false;
5151 }
5152 if (*m).len > 0 && !(*m).data.is_null() {
5153 ptr::copy_nonoverlapping((*m).data, data, (*m).len);
5154 }
5155 (*m).data = data;
5156 (*m).owned = true;
5157 (*m).cap = new_cap;
5158 return true;
5159 }
5160 let data = xmlReallocImpl((*m).data as *mut c_void, new_cap) as *mut u8;
5161 if data.is_null() {
5162 return false;
5163 }
5164 (*m).data = data;
5165 (*m).cap = new_cap;
5166 true
5167 }
5168}
5169
5170unsafe extern "C" fn pi_fd_read(context: *mut c_void, buffer: *mut c_char, len: c_int) -> c_int {
5172 unsafe {
5173 if context.is_null() || buffer.is_null() || len <= 0 {
5174 return -1;
5175 }
5176 let fd = *(context as *const c_int);
5177 libc::read(fd, buffer as *mut c_void, len as usize) as c_int
5178 }
5179}
5180
5181unsafe extern "C" fn pi_fd_close(context: *mut c_void) -> c_int {
5183 unsafe {
5184 if context.is_null() {
5185 return -1;
5186 }
5187 let _ = Box::from_raw(context as *mut c_int);
5188 0
5189 }
5190}
5191
5192unsafe extern "C" fn pi_file_read(context: *mut c_void, buffer: *mut c_char, len: c_int) -> c_int {
5194 unsafe {
5195 if context.is_null() || buffer.is_null() || len <= 0 {
5196 return -1;
5197 }
5198 libc::fread(buffer as *mut c_void, 1, len as usize, context as *mut libc::FILE) as c_int
5199 }
5200}
5201
5202#[no_mangle]
5208pub unsafe extern "C" fn xmlParserInputBufferCreateFd(fd: c_int, _enc: c_int) -> *mut _xmlParserInputBuffer {
5209 unsafe {
5210 if fd < 0 {
5211 return ptr::null_mut();
5212 }
5213 let buf = crate::xml::parser::helpers::alloc_parser_input_buffer();
5214 if buf.is_null() {
5215 return ptr::null_mut();
5216 }
5217 let fd_box = Box::into_raw(Box::new(fd));
5218 (*buf).context = fd_box as *mut c_void;
5219 (*buf).readcallback = Some(pi_fd_read);
5220 (*buf).closecallback = Some(pi_fd_close);
5221 (*buf).compressed = -1;
5222 (*buf).buffer = pi_mem_create() as *mut c_void;
5223 buf
5224 }
5225}
5226
5227#[no_mangle]
5233pub unsafe extern "C" fn xmlParserInputBufferCreateFile(
5234 file: *mut c_void,
5235 _enc: c_int,
5236) -> *mut _xmlParserInputBuffer {
5237 unsafe {
5238 if file.is_null() {
5239 return ptr::null_mut();
5240 }
5241 let buf = crate::xml::parser::helpers::alloc_parser_input_buffer();
5242 if buf.is_null() {
5243 return ptr::null_mut();
5244 }
5245 (*buf).context = file;
5246 (*buf).readcallback = Some(pi_file_read);
5247 (*buf).closecallback = None;
5248 (*buf).compressed = -1;
5249 (*buf).buffer = pi_mem_create() as *mut c_void;
5250 buf
5251 }
5252}
5253
5254#[no_mangle]
5261pub unsafe extern "C" fn xmlParserInputBufferCreateStatic(
5262 mem: *const c_char,
5263 size: c_int,
5264 _enc: c_int,
5265) -> *mut _xmlParserInputBuffer {
5266 unsafe {
5267 if mem.is_null() || size < 0 {
5268 return ptr::null_mut();
5269 }
5270 let buf = crate::xml::parser::helpers::alloc_parser_input_buffer();
5271 if buf.is_null() {
5272 return ptr::null_mut();
5273 }
5274 let m = pi_mem_create();
5275 if m.is_null() {
5276 crate::xml::parser::helpers::free_parser_input_buffer(buf);
5277 return ptr::null_mut();
5278 }
5279 (*m).data = mem as *mut u8;
5280 (*m).len = size as usize;
5281 (*m).cap = size as usize;
5282 (*m).owned = false;
5283 (*buf).buffer = m as *mut c_void;
5284 (*buf).compressed = -1;
5285 buf
5286 }
5287}
5288
5289unsafe extern "C" fn pi_default_input_buffer_create_filename(
5292 _uri: *const c_char,
5293 _enc: c_int,
5294) -> *mut _xmlParserInputBuffer {
5295 unsafe { crate::xml::parser::helpers::alloc_parser_input_buffer() }
5296}
5297
5298#[no_mangle]
5305pub unsafe extern "C" fn xmlParserInputBufferCreateFilenameDefault(
5306 func: Option<unsafe extern "C" fn(*const c_char, c_int) -> *mut _xmlParserInputBuffer>,
5307) -> Option<unsafe extern "C" fn(*const c_char, c_int) -> *mut _xmlParserInputBuffer> {
5308 unsafe {
5309 let default_fn: unsafe extern "C" fn(*const c_char, c_int) -> *mut _xmlParserInputBuffer =
5310 pi_default_input_buffer_create_filename;
5311 let old = xmlParserInputBufferCreateFilenameValue;
5312 xmlParserInputBufferCreateFilenameValue = if func == Some(default_fn) { None } else { func };
5313 old.or(Some(default_fn))
5314 }
5315}
5316