1#![allow(missing_docs)]
91#![allow(non_snake_case)]
92#![allow(non_camel_case_types)]
93#![allow(non_upper_case_globals)]
94#![allow(unused_variables)]
95#![allow(private_interfaces)]
96#![allow(clippy::missing_safety_doc)]
97#![allow(clippy::not_unsafe_ptr_arg_deref)]
98#![allow(clippy::too_many_arguments)]
99#![allow(dead_code)]
100#![allow(unused_assignments)]
101
102use core::ffi::c_void;
113use core::ptr;
114use std::mem::size_of;
115use std::os::raw::{c_char, c_int, c_uint, c_ulong};
116
117use crate::abi::allocator::{xmlFreeImpl, xmlMallocImpl, xmlMallocZero, xmlReallocImpl};
118use crate::abi::callbacks::_xmlSAXLocator;
119use crate::abi::structs::*;
120use crate::abi::types::*;
121use crate::xml::dtd::{create_content_model, create_int_subset, free_content_model};
122use crate::xml::parser::helpers::{
123 create_parser_ctxt, free_parser_ctxt, input_from_file, input_from_memory, setup_parser_input,
124};
125use crate::xml::sax::dispatch::SaxDispatcher;
126use crate::xml::validation::{is_xml_name_char, is_xml_name_start};
127
128const XML_PARSER_EOF_STATE: c_int = xmlParserInputState::XML_PARSER_EOF as c_int;
135const XML_PARSER_BUFFER_SIZE: usize = 512;
136const LINE_LEN: usize = 80;
137
138const XML_ENTITY_DECL: c_int = xmlElementType::XML_ENTITY_DECL as c_int;
142const XML_INTERNAL_GENERAL_ENTITY: c_int = xmlEntityType::XML_INTERNAL_GENERAL_ENTITY as c_int;
143const XML_EXTERNAL_GENERAL_PARSED_ENTITY: c_int =
144 xmlEntityType::XML_EXTERNAL_GENERAL_PARSED_ENTITY as c_int;
145const XML_INTERNAL_PARAMETER_ENTITY: c_int = xmlEntityType::XML_INTERNAL_PARAMETER_ENTITY as c_int;
146const XML_EXTERNAL_PARAMETER_ENTITY: c_int = xmlEntityType::XML_EXTERNAL_PARAMETER_ENTITY as c_int;
147const XML_INTERNAL_PREDEFINED_ENTITY: c_int =
148 xmlEntityType::XML_INTERNAL_PREDEFINED_ENTITY as c_int;
149const XML_ATTRIBUTE_CDATA: c_int = xmlAttributeType::XML_ATTRIBUTE_CDATA as c_int;
150const XML_ATTRIBUTE_ID: c_int = xmlAttributeType::XML_ATTRIBUTE_ID as c_int;
151const XML_ATTRIBUTE_IDREF: c_int = xmlAttributeType::XML_ATTRIBUTE_IDREF as c_int;
152const XML_ATTRIBUTE_IDREFS: c_int = xmlAttributeType::XML_ATTRIBUTE_IDREFS as c_int;
153const XML_ATTRIBUTE_ENTITY: c_int = xmlAttributeType::XML_ATTRIBUTE_ENTITY as c_int;
154const XML_ATTRIBUTE_ENTITIES: c_int = xmlAttributeType::XML_ATTRIBUTE_ENTITIES as c_int;
155const XML_ATTRIBUTE_NMTOKEN: c_int = xmlAttributeType::XML_ATTRIBUTE_NMTOKEN as c_int;
156const XML_ATTRIBUTE_NMTOKENS: c_int = xmlAttributeType::XML_ATTRIBUTE_NMTOKENS as c_int;
157const XML_ATTRIBUTE_ENUMERATION: c_int = xmlAttributeType::XML_ATTRIBUTE_ENUMERATION as c_int;
158const XML_ATTRIBUTE_NOTATION: c_int = xmlAttributeType::XML_ATTRIBUTE_NOTATION as c_int;
159const XML_ATTRIBUTE_NONE: c_int = xmlAttributeDefault::XML_ATTRIBUTE_NONE as c_int;
160const XML_ATTRIBUTE_REQUIRED: c_int = xmlAttributeDefault::XML_ATTRIBUTE_REQUIRED as c_int;
161const XML_ATTRIBUTE_IMPLIED: c_int = xmlAttributeDefault::XML_ATTRIBUTE_IMPLIED as c_int;
162const XML_ATTRIBUTE_FIXED: c_int = xmlAttributeDefault::XML_ATTRIBUTE_FIXED as c_int;
163const XML_ELEMENT_CONTENT_PCDATA: c_int =
164 xmlElementContentType::XML_ELEMENT_CONTENT_PCDATA as c_int;
165const XML_ELEMENT_CONTENT_ELEMENT: c_int =
166 xmlElementContentType::XML_ELEMENT_CONTENT_ELEMENT as c_int;
167const XML_ELEMENT_CONTENT_SEQ: c_int = xmlElementContentType::XML_ELEMENT_CONTENT_SEQ as c_int;
168const XML_ELEMENT_CONTENT_OR: c_int = xmlElementContentType::XML_ELEMENT_CONTENT_OR as c_int;
169const XML_ELEMENT_CONTENT_ONCE: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_ONCE as c_int;
170const XML_ELEMENT_CONTENT_OPT: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_OPT as c_int;
171const XML_ELEMENT_CONTENT_MULT: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_MULT as c_int;
172const XML_ELEMENT_CONTENT_PLUS: c_int = xmlElementContentOccur::XML_ELEMENT_CONTENT_PLUS as c_int;
173const XML_ELEMENT_TYPE_EMPTY: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_EMPTY as c_int;
174const XML_ELEMENT_TYPE_ANY: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_ANY as c_int;
175const XML_ELEMENT_TYPE_MIXED: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_MIXED as c_int;
176const XML_ELEMENT_TYPE_ELEMENT: c_int = xmlElementTypeVal::XML_ELEMENT_TYPE_ELEMENT as c_int;
177const XML_DOC_INTERNAL: c_int = xmlDocProperties::XML_DOC_INTERNAL as c_int;
178
179const XML_ERR_URI_REQUIRED: c_int = 100;
184const XML_ERR_PUBID_REQUIRED: c_int = 101;
185const XML_ERR_RESERVED_XML_NAME: c_int = 102;
186const XML_ERR_HYPHEN_IN_COMMENT: c_int = 103;
187const XML_ERR_EQUAL_REQUIRED: c_int = 104;
188const XML_ERR_SEPARATOR_REQUIRED: c_int = 105;
189const XML_ERR_INT_SUBSET_NOT_FINISHED: c_int = 106;
190const XML_ERR_UNKNOWN_VERSION: c_int = 107;
191const XML_ERR_ENCODING_NAME: c_int = 108;
192const XML_IO_UNKNOWN: c_int = 109;
193const XML_ERR_PCDATA_REQUIRED: c_int = 110;
194const XML_ERR_RESOURCE_LIMIT: c_int = 111;
195const XML_ERR_LTSLASH_REQUIRED: c_int = 112;
196
197unsafe impl Sync for _xmlEntity {}
200
201static PREDEF_AMP_NAME: [xmlChar; 4] = *b"amp\0";
206static PREDEF_LT_NAME: [xmlChar; 3] = *b"lt\0";
207static PREDEF_GT_NAME: [xmlChar; 3] = *b"gt\0";
208static PREDEF_QUOT_NAME: [xmlChar; 5] = *b"quot\0";
209static PREDEF_APOS_NAME: [xmlChar; 5] = *b"apos\0";
210static PREDEF_AMP_CONTENT: [xmlChar; 2] = *b"&\0";
211static PREDEF_LT_CONTENT: [xmlChar; 2] = *b"<\0";
212static PREDEF_GT_CONTENT: [xmlChar; 2] = *b">\0";
213static PREDEF_QUOT_CONTENT: [xmlChar; 2] = *b"\"\0";
214static PREDEF_APOS_CONTENT: [xmlChar; 2] = *b"'\0";
215
216static PREDEFINED_ENTITIES: [_xmlEntity; 5] = [
217 _xmlEntity {
218 _private: ptr::null_mut(),
219 type_: XML_ENTITY_DECL as c_int,
220 name: PREDEF_AMP_NAME.as_ptr(),
221 children: ptr::null_mut(),
222 last: ptr::null_mut(),
223 parent: ptr::null_mut(),
224 next: ptr::null_mut(),
225 prev: ptr::null_mut(),
226 doc: ptr::null_mut(),
227 orig: ptr::null_mut(),
228 content: PREDEF_AMP_CONTENT.as_ptr() as *mut xmlChar,
229 length: 1,
230 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
231 ExternalID: ptr::null(),
232 SystemID: ptr::null(),
233 nexte: ptr::null_mut(),
234 URI: ptr::null(),
235 owner: 0,
236 flags: 0,
237 expandedSize: 0,
238 },
239 _xmlEntity {
240 _private: ptr::null_mut(),
241 type_: XML_ENTITY_DECL as c_int,
242 name: PREDEF_LT_NAME.as_ptr(),
243 children: ptr::null_mut(),
244 last: ptr::null_mut(),
245 parent: ptr::null_mut(),
246 next: ptr::null_mut(),
247 prev: ptr::null_mut(),
248 doc: ptr::null_mut(),
249 orig: ptr::null_mut(),
250 content: PREDEF_LT_CONTENT.as_ptr() as *mut xmlChar,
251 length: 1,
252 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
253 ExternalID: ptr::null(),
254 SystemID: ptr::null(),
255 nexte: ptr::null_mut(),
256 URI: ptr::null(),
257 owner: 0,
258 flags: 0,
259 expandedSize: 0,
260 },
261 _xmlEntity {
262 _private: ptr::null_mut(),
263 type_: XML_ENTITY_DECL as c_int,
264 name: PREDEF_GT_NAME.as_ptr(),
265 children: ptr::null_mut(),
266 last: ptr::null_mut(),
267 parent: ptr::null_mut(),
268 next: ptr::null_mut(),
269 prev: ptr::null_mut(),
270 doc: ptr::null_mut(),
271 orig: ptr::null_mut(),
272 content: PREDEF_GT_CONTENT.as_ptr() as *mut xmlChar,
273 length: 1,
274 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
275 ExternalID: ptr::null(),
276 SystemID: ptr::null(),
277 nexte: ptr::null_mut(),
278 URI: ptr::null(),
279 owner: 0,
280 flags: 0,
281 expandedSize: 0,
282 },
283 _xmlEntity {
284 _private: ptr::null_mut(),
285 type_: XML_ENTITY_DECL as c_int,
286 name: PREDEF_QUOT_NAME.as_ptr(),
287 children: ptr::null_mut(),
288 last: ptr::null_mut(),
289 parent: ptr::null_mut(),
290 next: ptr::null_mut(),
291 prev: ptr::null_mut(),
292 doc: ptr::null_mut(),
293 orig: ptr::null_mut(),
294 content: PREDEF_QUOT_CONTENT.as_ptr() as *mut xmlChar,
295 length: 1,
296 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
297 ExternalID: ptr::null(),
298 SystemID: ptr::null(),
299 nexte: ptr::null_mut(),
300 URI: ptr::null(),
301 owner: 0,
302 flags: 0,
303 expandedSize: 0,
304 },
305 _xmlEntity {
306 _private: ptr::null_mut(),
307 type_: XML_ENTITY_DECL as c_int,
308 name: PREDEF_APOS_NAME.as_ptr(),
309 children: ptr::null_mut(),
310 last: ptr::null_mut(),
311 parent: ptr::null_mut(),
312 next: ptr::null_mut(),
313 prev: ptr::null_mut(),
314 doc: ptr::null_mut(),
315 orig: ptr::null_mut(),
316 content: PREDEF_APOS_CONTENT.as_ptr() as *mut xmlChar,
317 length: 1,
318 etype: XML_INTERNAL_PREDEFINED_ENTITY as c_int,
319 ExternalID: ptr::null(),
320 SystemID: ptr::null(),
321 nexte: ptr::null_mut(),
322 URI: ptr::null(),
323 owner: 0,
324 flags: 0,
325 expandedSize: 0,
326 },
327];
328
329#[inline]
334const fn pi_is_blank_ch(c: u8) -> bool {
335 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r'
336}
337
338#[inline]
339fn pi_is_byte_char(c: u8) -> bool {
340 c == 0x09 || c == 0x0A || c == 0x0D || (0x20..=0x7E).contains(&c) || (0xA0..=0xFF).contains(&c)
341}
342
343#[inline]
344const fn pi_is_pubidchar(c: u8) -> bool {
345 c == 0x20
346 || c == 0x0D
347 || c == 0x0A
348 || c.is_ascii_alphanumeric()
349 || matches!(
350 c,
351 b'-' | b'\''
352 | b'('
353 | b')'
354 | b'+'
355 | b','
356 | b'.'
357 | b'/'
358 | b':'
359 | b'='
360 | b'?'
361 | b';'
362 | b'!'
363 | b'*'
364 | b'#'
365 | b'@'
366 | b'$'
367 | b'_'
368 | b'%'
369 )
370}
371
372#[inline]
374const fn pi_is_char(c: c_int) -> bool {
375 matches!(c, 0x9 | 0xA | 0xD | 0x20..=0xD7FF | 0xE000..=0xFFFD | 0x10000..=0x10FFFF)
376}
377
378#[inline]
380const fn pi_is_letter_ch(c: u8) -> bool {
381 c.is_ascii_alphabetic()
382}
383
384#[inline]
386const fn pi_is_digit_ch(c: u8) -> bool {
387 c.is_ascii_digit()
388}
389
390const fn pi_is_name_start_char(c: c_int) -> bool {
392 if c < 0x80 {
393 return (c as u8).is_ascii_alphabetic() || c == b'_' as c_int || c == b':' as c_int;
394 }
395 if c > 0x10FFFF {
396 return false;
397 }
398 match char::from_u32(c as u32) {
399 Some(ch) => is_xml_name_start(ch),
400 None => false,
401 }
402}
403
404const fn pi_is_name_char(c: c_int) -> bool {
406 if c < 0x80 {
407 let b = c as u8;
408 return b.is_ascii_alphanumeric() || b == b'_' || b == b'-' || b == b'.' || b == b':';
409 }
410 if c > 0x10FFFF {
411 return false;
412 }
413 match char::from_u32(c as u32) {
414 Some(ch) => is_xml_name_char(ch),
415 None => false,
416 }
417}
418
419#[inline]
425unsafe fn pi_input(ctxt: *mut _xmlParserCtxt) -> *mut _xmlParserInput {
426 if ctxt.is_null() {
427 return ptr::null_mut();
428 }
429 unsafe { (*ctxt).input }
430}
431
432#[inline]
434unsafe fn pi_raw(ctxt: *mut _xmlParserCtxt) -> u8 {
435 let input = unsafe { pi_input(ctxt) };
436 if input.is_null() || unsafe { (*input).cur.is_null() } {
437 return 0;
438 }
439 unsafe { *(*input).cur }
440}
441
442#[inline]
444unsafe fn pi_nxt(ctxt: *mut _xmlParserCtxt, off: isize) -> u8 {
445 let input = unsafe { pi_input(ctxt) };
446 if input.is_null() || unsafe { (*input).cur.is_null() } {
447 return 0;
448 }
449 let cur = unsafe { (*input).cur };
450 let end = unsafe { (*input).end };
451 if off >= 0 {
452 if cur.offset(off) >= end {
453 return 0;
454 }
455 unsafe { *cur.offset(off) }
456 } else {
457 let base = unsafe { (*input).base };
459 if cur.offset(off) < base {
460 return 0;
461 }
462 unsafe { *cur.offset(off) }
463 }
464}
465
466#[inline]
468unsafe fn pi_cur_ptr(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
469 let input = unsafe { pi_input(ctxt) };
470 if input.is_null() {
471 return ptr::null();
472 }
473 unsafe { (*input).cur }
474}
475
476#[inline]
478unsafe fn pi_base_ptr(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
479 let input = unsafe { pi_input(ctxt) };
480 if input.is_null() {
481 return ptr::null();
482 }
483 unsafe { (*input).base }
484}
485
486unsafe fn pi_skip(ctxt: *mut _xmlParserCtxt, val: isize) {
488 let input = unsafe { pi_input(ctxt) };
489 if input.is_null() {
490 return;
491 }
492 unsafe {
493 let cur = (*input).cur;
494 let end = (*input).end;
495 let mut n = val;
496 while n > 0 && cur.offset(n) > end {
497 n -= 1;
498 }
499 (*input).col += val as c_int;
500 (*input).cur = cur.offset(val).min(end);
501 }
502}
503
504unsafe fn pi_next1(ctxt: *mut _xmlParserCtxt) {
506 let input = unsafe { pi_input(ctxt) };
507 if input.is_null() {
508 return;
509 }
510 unsafe {
511 if (*input).cur < (*input).end {
512 (*input).cur = (*input).cur.add(1);
513 (*input).col += 1;
514 }
515 }
516}
517
518unsafe fn pi_nextl(ctxt: *mut _xmlParserCtxt, l: usize) {
520 let input = unsafe { pi_input(ctxt) };
521 if input.is_null() {
522 return;
523 }
524 unsafe {
525 let cur = (*input).cur;
526 if cur < (*input).end {
527 if *cur == b'\n' {
528 (*input).line += 1;
529 (*input).col = 1;
530 } else {
531 (*input).col += 1;
532 }
533 (*input).cur = cur.add(l).min((*input).end);
534 }
535 }
536}
537
538unsafe fn pi_next_char(ctxt: *mut _xmlParserCtxt) {
540 let input = unsafe { pi_input(ctxt) };
541 if input.is_null() {
542 return;
543 }
544 unsafe {
545 let cur = (*input).cur;
546 if cur >= (*input).end {
547 return;
548 }
549 let c = *cur;
550 if c < 0x80 {
551 if c == b'\n' {
552 (*input).cur = cur.add(1);
553 (*input).line += 1;
554 (*input).col = 1;
555 } else if c == b'\r' {
556 if cur.add(1) < (*input).end && *cur.add(1) == b'\n' {
557 (*input).cur = cur.add(2);
558 } else {
559 (*input).cur = cur.add(1);
560 }
561 (*input).line += 1;
562 (*input).col = 1;
563 } else {
564 (*input).cur = cur.add(1);
565 (*input).col += 1;
566 }
567 } else {
568 (*input).col += 1;
569 let (_, l) = pi_decode_utf8(cur, (*input).end);
570 if l == 0 {
571 (*input).cur = cur.add(1);
572 } else {
573 (*input).cur = cur.add(l);
574 }
575 }
576 }
577}
578
579unsafe fn pi_decode_utf8(ptr: *const u8, end: *const u8) -> (c_int, usize) {
584 unsafe {
585 if ptr >= end {
586 return (0, 0);
587 }
588 let c = *ptr;
589 if c < 0x80 {
590 return (c as c_int, 1);
591 }
592 let avail = end.offset_from(ptr) as usize;
593 if (0xC2..=0xDF).contains(&c) && avail >= 2 && (*ptr.add(1) & 0xC0) == 0x80 {
594 let v = (((c as c_int) & 0x1F) << 6) | ((*ptr.add(1) as c_int) & 0x3F);
595 return (v, 2);
596 }
597 if c >= 0xE0 && avail >= 3 && (*ptr.add(1) & 0xC0) == 0x80 && (*ptr.add(2) & 0xC0) == 0x80 {
598 let v = (((c as c_int) & 0x0F) << 12)
599 | (((*ptr.add(1) as c_int) & 0x3F) << 6)
600 | ((*ptr.add(2) as c_int) & 0x3F);
601 if v >= 0x800 && !(0xD800..=0xDFFF).contains(&v) {
602 return (v, 3);
603 }
604 return (0xFFFD, 1);
605 }
606 if c >= 0xF0
607 && avail >= 4
608 && (*ptr.add(1) & 0xC0) == 0x80
609 && (*ptr.add(2) & 0xC0) == 0x80
610 && (*ptr.add(3) & 0xC0) == 0x80
611 {
612 let v = (((c as c_int) & 0x07) << 18)
613 | (((*ptr.add(1) as c_int) & 0x3F) << 12)
614 | (((*ptr.add(2) as c_int) & 0x3F) << 6)
615 | ((*ptr.add(3) as c_int) & 0x3F);
616 if (0x10000..=0x10FFFF).contains(&v) {
617 return (v, 4);
618 }
619 return (0xFFFD, 1);
620 }
621 (0xFFFD, 1)
622 }
623}
624
625unsafe fn pi_current_char(ctxt: *mut _xmlParserCtxt) -> (c_int, usize) {
627 let input = unsafe { pi_input(ctxt) };
628 if input.is_null() || unsafe { (*input).cur.is_null() } {
629 return (0, 0);
630 }
631 unsafe {
632 let cur = (*input).cur;
633 if cur >= (*input).end {
634 return (0, 0);
635 }
636 pi_decode_utf8(cur, (*input).end)
637 }
638}
639
640unsafe fn pi_current_char_recover(ctxt: *mut _xmlParserCtxt) -> (c_int, usize) {
642 let (c, l) = unsafe { pi_current_char(ctxt) };
643 if c == 0 {
644 (0xFFFD, 1)
645 } else {
646 (c, l)
647 }
648}
649
650#[inline]
652unsafe fn pi_stopped(ctxt: *mut _xmlParserCtxt) -> bool {
653 unsafe { (*ctxt).errNo != XML_ERR_OK || (*ctxt).disableSAX != 0 }
654}
655
656unsafe fn pi_fatal_err(ctxt: *mut _xmlParserCtxt, code: c_int) {
658 unsafe {
659 let c = &mut *ctxt;
660 if c.errNo == XML_ERR_OK {
661 c.errNo = code;
662 }
663 c.wellFormed = 0;
664 }
665}
666
667unsafe fn pi_err_memory(ctxt: *mut _xmlParserCtxt) {
669 unsafe {
670 let c = &mut *ctxt;
671 if c.errNo == XML_ERR_OK {
672 c.errNo = XML_ERR_NO_MEMORY;
673 }
674 c.wellFormed = 0;
675 }
676}
677
678unsafe fn pi_strndup_bytes(start: *const xmlChar, len: usize) -> *mut xmlChar {
680 unsafe {
681 let buf = xmlMallocImpl(len + 1) as *mut xmlChar;
682 if buf.is_null() {
683 return ptr::null_mut();
684 }
685 ptr::copy_nonoverlapping(start, buf, len);
686 *buf.add(len) = 0;
687 buf
688 }
689}
690
691fn pi_push_codepoint(buf: &mut Vec<u8>, c: c_int) {
693 if c < 0x80 {
694 buf.push(c as u8);
695 } else if c < 0x800 {
696 buf.push((0xC0 | ((c >> 6) & 0x1F)) as u8);
697 buf.push((0x80 | (c & 0x3F)) as u8);
698 } else if c < 0x10000 {
699 buf.push((0xE0 | ((c >> 12) & 0x0F)) as u8);
700 buf.push((0x80 | ((c >> 6) & 0x3F)) as u8);
701 buf.push((0x80 | (c & 0x3F)) as u8);
702 } else {
703 buf.push((0xF0 | ((c >> 18) & 0x07)) as u8);
704 buf.push((0x80 | ((c >> 12) & 0x3F)) as u8);
705 buf.push((0x80 | ((c >> 6) & 0x3F)) as u8);
706 buf.push((0x80 | (c & 0x3F)) as u8);
707 }
708}
709
710unsafe fn pi_skip_blanks(ctxt: *mut _xmlParserCtxt) -> c_int {
713 let mut res: c_int = 0;
714 unsafe {
715 loop {
716 if pi_stopped(ctxt) {
717 break;
718 }
719 let input = pi_input(ctxt);
720 if input.is_null() {
721 break;
722 }
723 if (*input).cur >= (*input).end || *(*input).cur == 0 {
724 if (*input).entity.is_null() || (*ctxt).inputNr <= 1 {
727 break;
728 }
729 pi_pop_pe(ctxt);
730 res = res.saturating_add(1);
731 continue;
732 }
733 let c = *(*input).cur;
734 if pi_is_blank_ch(c) {
735 pi_next_char(ctxt);
736 res = res.saturating_add(1);
737 } else {
738 break;
739 }
740 }
741 }
742 res
743}
744
745#[inline]
747unsafe fn pi_cmp6(ctxt: *mut _xmlParserCtxt, s: &[u8; 6]) -> bool {
748 unsafe {
749 pi_nxt(ctxt, 0) == s[0]
750 && pi_nxt(ctxt, 1) == s[1]
751 && pi_nxt(ctxt, 2) == s[2]
752 && pi_nxt(ctxt, 3) == s[3]
753 && pi_nxt(ctxt, 4) == s[4]
754 && pi_nxt(ctxt, 5) == s[5]
755 }
756}
757
758#[inline]
759unsafe fn pi_cmp5(ctxt: *mut _xmlParserCtxt, s: &[u8; 5]) -> bool {
760 unsafe {
761 pi_nxt(ctxt, 0) == s[0]
762 && pi_nxt(ctxt, 1) == s[1]
763 && pi_nxt(ctxt, 2) == s[2]
764 && pi_nxt(ctxt, 3) == s[3]
765 && pi_nxt(ctxt, 4) == s[4]
766 }
767}
768
769#[inline]
770unsafe fn pi_cmp7(ctxt: *mut _xmlParserCtxt, s: &[u8; 7]) -> bool {
771 unsafe { pi_cmp6(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5]]) && pi_nxt(ctxt, 6) == s[6] }
772}
773
774#[inline]
775unsafe fn pi_cmp8(ctxt: *mut _xmlParserCtxt, s: &[u8; 8]) -> bool {
776 unsafe { pi_cmp7(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5], s[6]]) && pi_nxt(ctxt, 7) == s[7] }
777}
778
779#[inline]
780unsafe fn pi_cmp9(ctxt: *mut _xmlParserCtxt, s: &[u8; 9]) -> bool {
781 unsafe {
782 pi_cmp8(ctxt, &[s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]]) && pi_nxt(ctxt, 8) == s[8]
783 }
784}
785
786#[inline]
787unsafe fn pi_cmp10(ctxt: *mut _xmlParserCtxt, s: &[u8; 10]) -> bool {
788 unsafe {
789 pi_cmp9(
790 ctxt,
791 &[s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8]],
792 ) && pi_nxt(ctxt, 9) == s[9]
793 }
794}
795
796unsafe fn pi_name_push(ctxt: *mut _xmlParserCtxt, name: *const xmlChar) -> c_int {
802 unsafe {
803 let c = &mut *ctxt;
804 if c.nameNr >= c.nameMax {
805 let new_max = if c.nameMax == 0 { 10 } else { c.nameMax * 2 };
806 let new_tab = xmlReallocImpl(
807 c.nameTab as *mut c_void,
808 (new_max as usize) * size_of::<*const xmlChar>(),
809 ) as *mut *const xmlChar;
810 if new_tab.is_null() {
811 return -1;
812 }
813 c.nameTab = new_tab;
814 c.nameMax = new_max;
815 }
816 *c.nameTab.add(c.nameNr as usize) = name;
817 c.nameNr += 1;
818 c.name = name;
819 }
820 0
821}
822
823unsafe fn pi_name_pop(ctxt: *mut _xmlParserCtxt) {
825 unsafe {
826 let c = &mut *ctxt;
827 if c.nameNr <= 0 {
828 return;
829 }
830 c.nameNr -= 1;
831 let old = *c.nameTab.add(c.nameNr as usize);
832 *c.nameTab.add(c.nameNr as usize) = ptr::null();
833 if c.nameNr == 0 {
834 c.name = ptr::null();
835 } else {
836 c.name = *c.nameTab.add((c.nameNr - 1) as usize);
837 }
838 if !old.is_null() {
839 xmlFreeImpl(old as *mut c_void);
840 }
841 }
842}
843
844unsafe fn pi_space_push(ctxt: *mut _xmlParserCtxt, val: c_int) -> c_int {
846 unsafe {
847 let c = &mut *ctxt;
848 if c.spaceNr >= c.spaceMax {
849 let new_max = if c.spaceMax == 0 { 10 } else { c.spaceMax * 2 };
850 let new_tab = xmlReallocImpl(
851 c.spaceTab as *mut c_void,
852 (new_max as usize) * size_of::<c_int>(),
853 ) as *mut c_int;
854 if new_tab.is_null() {
855 return -1;
856 }
857 c.spaceTab = new_tab;
858 c.spaceMax = new_max;
859 }
860 *c.spaceTab.add(c.spaceNr as usize) = val;
861 c.spaceNr += 1;
862 c.space = c.spaceTab.add((c.spaceNr - 1) as usize);
863 }
864 0
865}
866
867unsafe fn pi_space_pop(ctxt: *mut _xmlParserCtxt) {
869 unsafe {
870 let c = &mut *ctxt;
871 if c.spaceNr <= 0 {
872 return;
873 }
874 c.spaceNr -= 1;
875 if c.spaceNr == 0 {
876 c.space = ptr::null_mut();
877 } else {
878 c.space = c.spaceTab.add((c.spaceNr - 1) as usize);
879 }
880 }
881}
882
883unsafe fn pi_node_push(ctxt: *mut _xmlParserCtxt, node: *mut _xmlNode) -> c_int {
885 unsafe {
886 let c = &mut *ctxt;
887 if c.nodeNr >= c.nodeMax {
888 let new_max = if c.nodeMax == 0 { 10 } else { c.nodeMax * 2 };
889 let new_tab = xmlReallocImpl(
890 c.nodeTab as *mut c_void,
891 (new_max as usize) * size_of::<*mut _xmlNode>(),
892 ) as *mut *mut _xmlNode;
893 if new_tab.is_null() {
894 return -1;
895 }
896 c.nodeTab = new_tab;
897 c.nodeMax = new_max;
898 }
899 *c.nodeTab.add(c.nodeNr as usize) = node;
900 c.nodeNr += 1;
901 c.node = node;
902 }
903 0
904}
905
906unsafe fn pi_node_pop(ctxt: *mut _xmlParserCtxt) {
908 unsafe {
909 let c = &mut *ctxt;
910 if c.nodeNr <= 0 {
911 return;
912 }
913 c.nodeNr -= 1;
914 if c.nodeNr == 0 {
915 c.node = ptr::null_mut();
916 } else {
917 c.node = *c.nodeTab.add((c.nodeNr - 1) as usize);
918 }
919 }
920}
921
922unsafe fn pi_input_push(ctxt: *mut _xmlParserCtxt, input: *mut _xmlParserInput) -> c_int {
924 unsafe {
925 if ctxt.is_null() || input.is_null() {
926 return -1;
927 }
928 let c = &mut *ctxt;
929 if c.inputNr >= c.inputMax {
930 let new_max = if c.inputMax == 0 { 4 } else { c.inputMax * 2 };
931 let new_tab = xmlReallocImpl(
932 c.inputTab as *mut c_void,
933 (new_max as usize) * size_of::<*mut _xmlParserInput>(),
934 ) as *mut *mut _xmlParserInput;
935 if new_tab.is_null() {
936 return -1;
937 }
938 c.inputTab = new_tab;
939 c.inputMax = new_max;
940 }
941 *c.inputTab.add(c.inputNr as usize) = input;
942 c.input = input;
943 c.inputNr += 1;
944 }
945 0
946}
947
948unsafe fn pi_input_pop(ctxt: *mut _xmlParserCtxt) -> *mut _xmlParserInput {
950 unsafe {
951 if ctxt.is_null() {
952 return ptr::null_mut();
953 }
954 let c = &mut *ctxt;
955 if c.inputNr <= 0 {
956 return ptr::null_mut();
957 }
958 c.inputNr -= 1;
959 if c.inputNr > 0 {
960 c.input = *c.inputTab.add((c.inputNr - 1) as usize);
961 } else {
962 c.input = ptr::null_mut();
963 }
964 let ret = *c.inputTab.add(c.inputNr as usize);
965 *c.inputTab.add(c.inputNr as usize) = ptr::null_mut();
966 ret
967 }
968}
969
970unsafe fn pi_pop_pe(ctxt: *mut _xmlParserCtxt) {
972 unsafe {
973 let input = pi_input_pop(ctxt);
974 if input.is_null() {
975 return;
976 }
977 let base = (*input).base;
978 if !base.is_null() && !(*input).entity.is_null() {
979 xmlFreeImpl(base as *mut c_void);
980 }
981 if !(*input).filename.is_null() {
984 xmlFreeImpl((*input).filename as *mut c_void);
985 }
986 xmlFreeImpl(input as *mut c_void);
987 }
988}
989
990unsafe fn pi_ctxt_late_init(ctxt: *mut _xmlParserCtxt) {
992 unsafe {
993 if ctxt.is_null() {
994 return;
995 }
996 let c = &mut *ctxt;
997 if !c.sax.is_null() && (*c.sax).initialized == XML_SAX2_MAGIC as c_uint {
998 c.sax2 = 1;
999 }
1000 }
1001}
1002
1003const unsafe fn pi_split_qname(qname: *const xmlChar) -> (*const xmlChar, *const xmlChar) {
1005 if qname.is_null() {
1006 return (ptr::null(), ptr::null());
1007 }
1008 unsafe {
1009 let mut p = qname;
1010 while *p != 0 {
1011 if *p == b':' {
1012 return (p.add(1), qname);
1013 }
1014 p = p.add(1);
1015 }
1016 }
1017 (qname, ptr::null())
1018}
1019
1020const unsafe fn pi_cstr_eq(s: *const xmlChar, bytes: &[u8]) -> bool {
1022 if s.is_null() {
1023 return bytes.is_empty();
1024 }
1025 unsafe {
1026 let mut i = 0usize;
1027 loop {
1028 let b = *s.add(i);
1029 if i >= bytes.len() {
1030 return b == 0;
1031 }
1032 if b != bytes[i] {
1033 return false;
1034 }
1035 i += 1;
1036 }
1037 }
1038}
1039
1040unsafe fn pi_get_predefined_entity(name: *const xmlChar) -> *mut _xmlEntity {
1046 if name.is_null() {
1047 return ptr::null_mut();
1048 }
1049 for e in PREDEFINED_ENTITIES.iter() {
1050 if unsafe { crate::abi::exports_xml2::xmlStrcmp(e.name, name) == 0 } {
1051 return e as *const _xmlEntity as *mut _xmlEntity;
1052 }
1053 }
1054 ptr::null_mut()
1055}
1056
1057unsafe fn pi_lookup_general_entity(
1060 ctxt: *mut _xmlParserCtxt,
1061 name: *const xmlChar,
1062) -> *mut _xmlEntity {
1063 unsafe {
1064 if (*ctxt).options & XML_PARSE_OLDSAX == 0 {
1066 let ent = pi_get_predefined_entity(name);
1067 if !ent.is_null() {
1068 return ent;
1069 }
1070 }
1071 let c = &*ctxt;
1072 if !c.sax.is_null() {
1073 let ent = SaxDispatcher::get_entity(&*c.sax, c.userData, name);
1074 if !ent.is_null() {
1075 return ent;
1076 }
1077 if c.userData == ctxt as *mut c_void {
1078 let ent2 = crate::abi::exports_xml2::xmlSAX2GetEntity(c.userData, name);
1079 if !ent2.is_null() {
1080 return ent2;
1081 }
1082 }
1083 }
1084 ptr::null_mut()
1085 }
1086}
1087
1088unsafe fn pi_lookup_parameter_entity(
1090 ctxt: *mut _xmlParserCtxt,
1091 name: *const xmlChar,
1092) -> *mut _xmlEntity {
1093 unsafe {
1094 let c = &*ctxt;
1095 if !c.sax.is_null() {
1096 let ent = SaxDispatcher::get_parameter_entity(&*c.sax, c.userData, name);
1097 if !ent.is_null() {
1098 return ent;
1099 }
1100 if c.userData == ctxt as *mut c_void {
1101 let ent2 = crate::abi::exports_xml2::xmlSAX2GetParameterEntity(c.userData, name);
1102 if !ent2.is_null() {
1103 return ent2;
1104 }
1105 }
1106 }
1107 ptr::null_mut()
1108 }
1109}
1110
1111unsafe fn pi_sax_chars(ctxt: *mut _xmlParserCtxt, bytes: &[u8], ignorable: bool) {
1117 if bytes.is_empty() {
1118 return;
1119 }
1120 unsafe {
1121 let c = &*ctxt;
1122 if c.sax.is_null() || c.disableSAX != 0 {
1123 return;
1124 }
1125 let buf = pi_strndup_bytes(bytes.as_ptr(), bytes.len());
1126 if buf.is_null() {
1127 return;
1128 }
1129 if ignorable {
1130 SaxDispatcher::ignorable_whitespace(&*c.sax, c.userData, buf, bytes.len() as c_int);
1131 } else {
1132 SaxDispatcher::characters(&*c.sax, c.userData, buf, bytes.len() as c_int);
1133 }
1134 xmlFreeImpl(buf as *mut c_void);
1135 }
1136}
1137
1138unsafe fn pi_sax_comment(ctxt: *mut _xmlParserCtxt, bytes: &[u8]) {
1140 unsafe {
1141 let c = &*ctxt;
1142 if c.sax.is_null() || c.disableSAX != 0 {
1143 return;
1144 }
1145 let buf = if bytes.is_empty() {
1146 ptr::null()
1147 } else {
1148 pi_strndup_bytes(bytes.as_ptr(), bytes.len())
1149 };
1150 if bytes.is_empty() || !buf.is_null() {
1151 SaxDispatcher::comment(&*c.sax, c.userData, buf);
1152 }
1153 if !buf.is_null() {
1154 xmlFreeImpl(buf as *mut c_void);
1155 }
1156 }
1157}
1158
1159unsafe fn pi_sax_pi(ctxt: *mut _xmlParserCtxt, target: *const xmlChar, data: &[u8]) {
1161 unsafe {
1162 let c = &*ctxt;
1163 if c.sax.is_null() || c.disableSAX != 0 {
1164 return;
1165 }
1166 let buf = if data.is_empty() {
1167 ptr::null()
1168 } else {
1169 pi_strndup_bytes(data.as_ptr(), data.len())
1170 };
1171 if data.is_empty() || !buf.is_null() {
1172 SaxDispatcher::processing_instruction(&*c.sax, c.userData, target, buf);
1173 }
1174 if !buf.is_null() {
1175 xmlFreeImpl(buf as *mut c_void);
1176 }
1177 }
1178}
1179
1180unsafe fn pi_dispatch_start_element(
1187 ctxt: *mut _xmlParserCtxt,
1188 qname: *const xmlChar,
1189 atts: *mut *const xmlChar,
1190 nbatts: usize,
1191) {
1192 unsafe {
1193 let c = &*ctxt;
1194 if c.sax.is_null() || c.disableSAX != 0 {
1195 return;
1196 }
1197 let sax = &*c.sax;
1198 let (local, prefix) = pi_split_qname(qname);
1199 if let Some(cb2) = sax.startElementNs {
1200 let nattr = nbatts / 2;
1201 let mut namespaces: Vec<*const xmlChar> = Vec::new();
1202 let mut attrs2: Vec<*const xmlChar> = Vec::new();
1203 for k in 0..nattr {
1204 let aname = *atts.add(k * 2);
1205 let aval = *atts.add(k * 2 + 1);
1206 if aname.is_null() {
1207 continue;
1208 }
1209 let (alocal, apref) = pi_split_qname(aname);
1210 if apref.is_null() && pi_cstr_eq(aname, b"xmlns") {
1211 namespaces.push(ptr::null());
1212 namespaces.push(aval);
1213 } else if !apref.is_null() && pi_cstr_eq(apref, b"xmlns") {
1214 namespaces.push(alocal);
1215 namespaces.push(aval);
1216 } else {
1217 attrs2.push(alocal);
1218 attrs2.push(apref);
1219 attrs2.push(ptr::null());
1220 attrs2.push(aval);
1221 attrs2.push(aval.add(crate::abi::exports_xml2::xmlStrlen(aval) as usize));
1222 }
1223 }
1224 cb2(
1225 c.userData,
1226 local,
1227 prefix,
1228 ptr::null(),
1229 (namespaces.len() / 2) as c_int,
1230 namespaces.as_mut_ptr(),
1231 (attrs2.len() / 5) as c_int,
1232 0,
1233 attrs2.as_mut_ptr(),
1234 );
1235 } else if let Some(cb1) = sax.startElement {
1236 let sa1 = if nbatts > 0 {
1237 let mut arr: Vec<*const xmlChar> = Vec::with_capacity(nbatts + 2);
1239 for i in 0..nbatts {
1240 arr.push(*atts.add(i));
1241 }
1242 arr.push(ptr::null());
1243 arr.push(ptr::null());
1244 arr.as_mut_ptr()
1245 } else {
1246 ptr::null_mut()
1247 };
1248 cb1(c.userData, qname, sa1);
1249 }
1250 }
1251}
1252
1253unsafe fn pi_dispatch_end_element(ctxt: *mut _xmlParserCtxt, qname: *const xmlChar) {
1255 unsafe {
1256 let c = &*ctxt;
1257 if c.sax.is_null() || c.disableSAX != 0 {
1258 return;
1259 }
1260 let sax = &*c.sax;
1261 let (local, prefix) = pi_split_qname(qname);
1262 if let Some(cb2) = sax.endElementNs {
1263 cb2(c.userData, local, prefix, ptr::null());
1264 } else if let Some(cb1) = sax.endElement {
1265 cb1(c.userData, qname);
1266 }
1267 }
1268}
1269
1270unsafe fn pi_parse_name(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
1277 unsafe {
1278 let input = pi_input(ctxt);
1279 if input.is_null() || (*input).cur.is_null() {
1280 return ptr::null();
1281 }
1282 let in_ptr = (*input).cur;
1283 let end = (*input).end;
1284 let first = *in_ptr;
1285
1286 if (first.is_ascii_lowercase()
1288 || first.is_ascii_uppercase()
1289 || first == b'_'
1290 || first == b':')
1291 && in_ptr < end
1292 {
1293 let mut p = in_ptr.add(1);
1294 while p < end {
1295 let b = *p;
1296 if b.is_ascii_alphanumeric() || b == b'_' || b == b'-' || b == b':' || b == b'.' {
1297 p = p.add(1);
1298 } else {
1299 break;
1300 }
1301 }
1302 if p >= end || (*p > 0 && *p < 0x80) {
1303 let count = p.offset_from(in_ptr) as usize;
1304 if count > 0 {
1305 let ret = pi_strndup_bytes(in_ptr, count);
1306 if ret.is_null() {
1307 pi_err_memory(ctxt);
1308 return ptr::null();
1309 }
1310 (*input).cur = p;
1311 (*input).col += count as c_int;
1312 return ret;
1313 }
1314 }
1315 }
1316
1317 let start = (*input).cur;
1319 let (c, l) = pi_current_char(ctxt);
1320 if !pi_is_name_start_char(c) {
1321 return ptr::null();
1322 }
1323 let mut len = l;
1324 pi_nextl(ctxt, l);
1325 loop {
1326 let (c2, l2) = pi_current_char(ctxt);
1327 if !pi_is_name_char(c2) {
1328 break;
1329 }
1330 len += l2;
1331 pi_nextl(ctxt, l2);
1332 }
1333 let ret = pi_strndup_bytes(start, len);
1334 if ret.is_null() {
1335 pi_err_memory(ctxt);
1336 }
1337 ret
1338 }
1339}
1340
1341unsafe fn pi_parse_nmtoken(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1343 unsafe {
1344 let mut buf: Vec<u8> = Vec::new();
1345 loop {
1346 let (c, l) = pi_current_char(ctxt);
1347 if !pi_is_name_char(c) {
1348 break;
1349 }
1350 pi_push_codepoint(&mut buf, c);
1351 pi_nextl(ctxt, l);
1352 }
1353 if buf.is_empty() {
1354 return ptr::null_mut();
1355 }
1356 let ret = pi_strndup_bytes(buf.as_ptr(), buf.len());
1357 if ret.is_null() {
1358 pi_err_memory(ctxt);
1359 }
1360 ret
1361 }
1362}
1363
1364unsafe fn pi_parse_name_and_compare(
1366 ctxt: *mut _xmlParserCtxt,
1367 other: *const xmlChar,
1368) -> *const xmlChar {
1369 unsafe {
1370 let input = pi_input(ctxt);
1371 if input.is_null() || other.is_null() {
1372 return ptr::null();
1373 }
1374 let mut in_ptr = (*input).cur;
1375 let mut cmp = other;
1376 while !in_ptr.is_null() && *in_ptr != 0 && *in_ptr == *cmp {
1377 in_ptr = in_ptr.add(1);
1378 cmp = cmp.add(1);
1379 }
1380 if *cmp == 0 && (*in_ptr == b'>' || pi_is_blank_ch(*in_ptr)) {
1381 (*input).col += in_ptr.offset_from((*input).cur) as c_int;
1382 (*input).cur = in_ptr;
1383 return std::ptr::dangling::<xmlChar>();
1384 }
1385 let ret = pi_parse_name(ctxt);
1386 if !ret.is_null() && crate::abi::exports_xml2::xmlStrcmp(ret, other) == 0 {
1387 xmlFreeImpl(ret as *mut c_void);
1388 return std::ptr::dangling::<xmlChar>();
1389 }
1390 ret
1391 }
1392}
1393
1394unsafe fn pi_parse_char_ref(ctxt: *mut _xmlParserCtxt) -> c_int {
1396 unsafe {
1397 let mut val: c_int = 0;
1398 let mut count: c_int = 0;
1399 if pi_raw(ctxt) == b'&' && pi_nxt(ctxt, 1) == b'#' && pi_nxt(ctxt, 2) == b'x' {
1400 pi_skip(ctxt, 3);
1401 while pi_raw(ctxt) != b';' && !pi_stopped(ctxt) {
1402 if count > 20 {
1403 count = 0;
1404 }
1405 let c = pi_raw(ctxt);
1406 if c.is_ascii_digit() {
1407 val = val * 16 + (c - b'0') as c_int;
1408 } else if (b'a'..=b'f').contains(&c) {
1409 val = val * 16 + (c - b'a') as c_int + 10;
1410 } else if (b'A'..=b'F').contains(&c) {
1411 val = val * 16 + (c - b'A') as c_int + 10;
1412 } else {
1413 pi_fatal_err(ctxt, XML_ERR_INVALID_HEX_CHARREF);
1414 val = 0;
1415 break;
1416 }
1417 if val > 0x110000 {
1418 val = 0x110000;
1419 }
1420 pi_next1(ctxt);
1421 count += 1;
1422 }
1423 if pi_raw(ctxt) == b';' {
1424 pi_next1(ctxt);
1425 }
1426 } else if pi_raw(ctxt) == b'&' && pi_nxt(ctxt, 1) == b'#' {
1427 pi_skip(ctxt, 2);
1428 while pi_raw(ctxt) != b';' {
1429 if count > 20 {
1430 count = 0;
1431 }
1432 let c = pi_raw(ctxt);
1433 if c.is_ascii_digit() {
1434 val = val * 10 + (c - b'0') as c_int;
1435 } else {
1436 pi_fatal_err(ctxt, XML_ERR_INVALID_DEC_CHARREF);
1437 val = 0;
1438 break;
1439 }
1440 if val > 0x110000 {
1441 val = 0x110000;
1442 }
1443 pi_next1(ctxt);
1444 count += 1;
1445 }
1446 if pi_raw(ctxt) == b';' {
1447 pi_next1(ctxt);
1448 }
1449 } else {
1450 if pi_raw(ctxt) == b'&' {
1451 pi_skip(ctxt, 1);
1452 }
1453 pi_fatal_err(ctxt, XML_ERR_INVALID_CHARREF);
1454 }
1455
1456 if val >= 0x110000 {
1458 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1459 val = 0xFFFD;
1460 } else if !pi_is_char(val) {
1461 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1462 }
1463 val
1464 }
1465}
1466
1467unsafe fn pi_parse_entity_ref(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEntity {
1469 unsafe {
1470 if ctxt.is_null() {
1471 return ptr::null_mut();
1472 }
1473 let name = pi_parse_entity_ref_name(ctxt);
1474 if name.is_null() {
1475 return ptr::null_mut();
1476 }
1477 let ent = pi_lookup_general_entity(ctxt, name);
1478 xmlFreeImpl(name as *mut c_void);
1479 ent
1480 }
1481}
1482
1483unsafe fn pi_parse_entity_ref_name(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
1485 unsafe {
1486 if pi_raw(ctxt) != b'&' {
1487 return ptr::null();
1488 }
1489 pi_next1(ctxt);
1490 let name = pi_parse_name(ctxt);
1491 if name.is_null() {
1492 pi_fatal_err(ctxt, XML_ERR_ENTITYREF_NO_NAME);
1493 return ptr::null();
1494 }
1495 if pi_raw(ctxt) != b';' {
1496 pi_fatal_err(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING);
1497 xmlFreeImpl(name as *mut c_void);
1498 return ptr::null();
1499 }
1500 pi_next1(ctxt);
1501 name
1502 }
1503}
1504
1505unsafe fn pi_parse_entity_value(
1507 ctxt: *mut _xmlParserCtxt,
1508 orig: *mut *mut xmlChar,
1509) -> *mut xmlChar {
1510 unsafe {
1511 let quote = pi_raw(ctxt);
1512 if quote != b'"' && quote != b'\'' {
1513 pi_fatal_err(ctxt, XML_ERR_ENTITY_NOT_STARTED);
1514 return ptr::null_mut();
1515 }
1516 let start = pi_cur_ptr(ctxt);
1517 pi_next1(ctxt);
1518 let mut len: usize = 0;
1519 loop {
1520 if pi_stopped(ctxt) {
1521 return ptr::null_mut();
1522 }
1523 let input = pi_input(ctxt);
1524 if input.is_null() || (*input).cur >= (*input).end {
1525 pi_fatal_err(ctxt, XML_ERR_ENTITY_NOT_FINISHED);
1526 return ptr::null_mut();
1527 }
1528 let c = pi_raw(ctxt);
1529 if c == 0 {
1530 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1531 return ptr::null_mut();
1532 }
1533 if c == quote {
1534 break;
1535 }
1536 pi_next1(ctxt);
1537 len += 1;
1538 }
1539 if !orig.is_null() {
1540 *orig = pi_strndup_bytes(start, len);
1541 }
1542 let val = pi_strndup_bytes(start, len);
1543 pi_next1(ctxt);
1544 val
1545 }
1546}
1547
1548unsafe fn pi_parse_att_value(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1551 unsafe {
1552 if ctxt.is_null() || pi_input(ctxt).is_null() {
1553 return ptr::null_mut();
1554 }
1555 let quote = pi_raw(ctxt);
1556 if quote != b'"' && quote != b'\'' {
1557 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED);
1558 return ptr::null_mut();
1559 }
1560 pi_next1(ctxt);
1561 let replace_entities = (*ctxt).replaceEntities != 0;
1562 let mut out: Vec<u8> = Vec::new();
1563 loop {
1564 if pi_stopped(ctxt) {
1565 return ptr::null_mut();
1566 }
1567 let input = pi_input(ctxt);
1568 if input.is_null() {
1569 return ptr::null_mut();
1570 }
1571 if (*input).cur >= (*input).end {
1572 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED);
1573 return ptr::null_mut();
1574 }
1575 let c = pi_raw(ctxt);
1576 if c == quote {
1577 break;
1578 }
1579 if c >= 0x80 {
1580 let (ch, l) = pi_current_char(ctxt);
1581 if ch == 0 {
1582 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1583 return ptr::null_mut();
1584 }
1585 pi_push_codepoint(&mut out, ch);
1586 pi_nextl(ctxt, l);
1587 } else if c == b'&' {
1588 if pi_nxt(ctxt, 1) == b'#' {
1589 let val = pi_parse_char_ref(ctxt);
1590 if val == 0 {
1591 return ptr::null_mut();
1592 }
1593 if val == b'&' as c_int && !replace_entities {
1594 out.extend_from_slice(b"&");
1595 } else {
1596 pi_push_codepoint(&mut out, val);
1597 }
1598 } else {
1599 let name = pi_parse_entity_ref_name(ctxt);
1600 if name.is_null() {
1601 return ptr::null_mut();
1602 }
1603 let ent = pi_lookup_general_entity(ctxt, name);
1604 let mut expanded = false;
1605 if !ent.is_null() {
1606 let etype = (*ent).etype;
1607 let content = (*ent).content;
1608 if !content.is_null() {
1609 if etype == XML_INTERNAL_PREDEFINED_ENTITY as c_int {
1610 if *content == b'&' && !replace_entities {
1611 out.extend_from_slice(b"&");
1612 } else {
1613 let l = crate::abi::exports_xml2::xmlStrlen(content) as usize;
1614 out.extend_from_slice(core::slice::from_raw_parts(content, l));
1615 }
1616 expanded = true;
1617 } else if replace_entities
1618 && etype == XML_INTERNAL_GENERAL_ENTITY as c_int
1619 {
1620 let l = crate::abi::exports_xml2::xmlStrlen(content) as usize;
1621 out.extend_from_slice(core::slice::from_raw_parts(content, l));
1622 expanded = true;
1623 }
1624 }
1625 }
1626 if !expanded {
1627 out.push(b'&');
1628 let l = crate::abi::exports_xml2::xmlStrlen(name) as usize;
1629 out.extend_from_slice(core::slice::from_raw_parts(name, l));
1630 out.push(b';');
1631 }
1632 xmlFreeImpl(name as *mut c_void);
1633 }
1634 } else {
1635 if c == b'<' {
1636 pi_fatal_err(ctxt, XML_ERR_LT_IN_ATTRIBUTE);
1637 }
1638 if c < 0x20 {
1639 out.push(b' ');
1641 if c == b'\r' && pi_nxt(ctxt, 1) == b'\n' {
1642 pi_next1(ctxt);
1643 }
1644 } else {
1645 out.push(c);
1646 }
1647 pi_next1(ctxt);
1648 }
1649 }
1650 pi_next1(ctxt);
1651 out.push(0);
1652
1653 pi_strndup_bytes(out.as_ptr(), out.len() - 1)
1654 }
1655}
1656
1657unsafe fn pi_parse_system_literal(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1659 unsafe {
1660 let stop = if pi_raw(ctxt) == b'"' {
1661 pi_next1(ctxt);
1662 b'"'
1663 } else if pi_raw(ctxt) == b'\'' {
1664 pi_next1(ctxt);
1665 b'\''
1666 } else {
1667 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_STARTED);
1668 return ptr::null_mut();
1669 };
1670 let mut buf: Vec<u8> = Vec::new();
1671 loop {
1672 let (cur, l) = pi_current_char_recover(ctxt);
1673 if !pi_is_char(cur) || cur == stop as c_int {
1674 break;
1675 }
1676 pi_push_codepoint(&mut buf, cur);
1677 pi_nextl(ctxt, l);
1678 }
1679 let cur = pi_raw(ctxt);
1680 if !pi_is_char(cur as c_int) {
1681 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_FINISHED);
1682 } else if cur == stop {
1683 pi_next1(ctxt);
1684 }
1685 pi_strndup_bytes(buf.as_ptr(), buf.len())
1686 }
1687}
1688
1689unsafe fn pi_parse_pubid_literal(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1691 unsafe {
1692 let stop = if pi_raw(ctxt) == b'"' {
1693 pi_next1(ctxt);
1694 b'"'
1695 } else if pi_raw(ctxt) == b'\'' {
1696 pi_next1(ctxt);
1697 b'\''
1698 } else {
1699 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_STARTED);
1700 return ptr::null_mut();
1701 };
1702 let mut buf: Vec<u8> = Vec::new();
1703 loop {
1704 let cur = pi_raw(ctxt);
1705 if !pi_is_pubidchar(cur) || cur == stop {
1706 break;
1707 }
1708 buf.push(cur);
1709 pi_next1(ctxt);
1710 }
1711 if pi_raw(ctxt) != stop {
1712 pi_fatal_err(ctxt, XML_ERR_LITERAL_NOT_FINISHED);
1713 } else {
1714 pi_next1(ctxt);
1715 }
1716 pi_strndup_bytes(buf.as_ptr(), buf.len())
1717 }
1718}
1719
1720unsafe fn pi_parse_quoted_string(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
1722 unsafe {
1723 if ctxt.is_null() || pi_input(ctxt).is_null() {
1724 return ptr::null_mut();
1725 }
1726 let ret = pi_parse_att_value(ctxt);
1727 if ret.is_null() {
1728 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
1729 }
1730 ret
1731 }
1732}
1733
1734unsafe fn pi_parse_external_id(
1736 ctxt: *mut _xmlParserCtxt,
1737 public_id: *mut *mut xmlChar,
1738 strict: c_int,
1739) -> *mut xmlChar {
1740 unsafe {
1741 *public_id = ptr::null_mut();
1742 let mut uri: *mut xmlChar = ptr::null_mut();
1743 if pi_cmp6(ctxt, b"SYSTEM") {
1744 pi_skip(ctxt, 6);
1745 pi_skip_blanks(ctxt);
1746 uri = pi_parse_system_literal(ctxt);
1747 if uri.is_null() {
1748 pi_fatal_err(ctxt, XML_ERR_URI_REQUIRED);
1749 }
1750 } else if pi_cmp6(ctxt, b"PUBLIC") {
1751 pi_skip(ctxt, 6);
1752 pi_skip_blanks(ctxt);
1753 *public_id = pi_parse_pubid_literal(ctxt);
1754 if public_id.is_null() || (*public_id).is_null() {
1755 pi_fatal_err(ctxt, XML_ERR_PUBID_REQUIRED);
1756 }
1757 if strict != 0 {
1758 if pi_skip_blanks(ctxt) == 0 {
1759 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
1760 }
1761 } else {
1762 if pi_skip_blanks(ctxt) == 0 {
1763 return ptr::null_mut();
1764 }
1765 if pi_raw(ctxt) != b'\'' && pi_raw(ctxt) != b'"' {
1766 return ptr::null_mut();
1767 }
1768 }
1769 uri = pi_parse_system_literal(ctxt);
1770 if uri.is_null() {
1771 pi_fatal_err(ctxt, XML_ERR_URI_REQUIRED);
1772 }
1773 }
1774 uri
1775 }
1776}
1777
1778unsafe fn pi_parse_pi_target(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
1780 unsafe {
1781 let name = pi_parse_name(ctxt);
1782 if name.is_null() {
1783 return ptr::null();
1784 }
1785 let len = crate::abi::exports_xml2::xmlStrlen(name) as usize;
1786 if len >= 3 {
1787 let c0 = *name;
1788 let c1 = *name.add(1);
1789 let c2 = *name.add(2);
1790 if (c0 == b'x' || c0 == b'X')
1791 && (c1 == b'm' || c1 == b'M')
1792 && (c2 == b'l' || c2 == b'L')
1793 {
1794 if len == 3 || !(c0 == b'x' && c1 == b'm' && c2 == b'l') {
1796 pi_fatal_err(ctxt, XML_ERR_RESERVED_XML_NAME);
1797 }
1798 }
1799 }
1800 if !crate::abi::exports_xml2::xmlStrchr(name, b':').is_null() {
1801 }
1803 name
1804 }
1805}
1806
1807unsafe fn pi_parse_pi(ctxt: *mut _xmlParserCtxt) {
1809 unsafe {
1810 if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'?' {
1811 pi_skip(ctxt, 2);
1812 let target = pi_parse_pi_target(ctxt);
1813 if !target.is_null() {
1814 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
1815 pi_skip(ctxt, 2);
1816 pi_sax_pi(ctxt, target, &[]);
1817 xmlFreeImpl(target as *mut c_void);
1818 return;
1819 }
1820 if pi_skip_blanks(ctxt) == 0 {
1821 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
1822 }
1823 let mut buf: Vec<u8> = Vec::new();
1824 loop {
1825 let (cur, l) = pi_current_char_recover(ctxt);
1826 if !pi_is_char(cur) || (cur == b'?' as c_int && pi_nxt(ctxt, 1) == b'>') {
1827 break;
1828 }
1829 pi_push_codepoint(&mut buf, cur);
1830 pi_nextl(ctxt, l);
1831 }
1832 if pi_raw(ctxt) != b'?' {
1833 pi_fatal_err(ctxt, XML_ERR_PI_NOT_FINISHED);
1834 } else {
1835 pi_skip(ctxt, 2);
1836 pi_sax_pi(ctxt, target, &buf);
1837 }
1838 xmlFreeImpl(target as *mut c_void);
1839 } else {
1840 pi_fatal_err(ctxt, XML_ERR_PI_NOT_STARTED);
1841 }
1842 }
1843 }
1844}
1845
1846unsafe fn pi_parse_comment(ctxt: *mut _xmlParserCtxt) {
1848 unsafe {
1849 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
1850 return;
1851 }
1852 pi_skip(ctxt, 2);
1853 if pi_raw(ctxt) != b'-' || pi_nxt(ctxt, 1) != b'-' {
1854 return;
1855 }
1856 pi_skip(ctxt, 2);
1857
1858 let mut buf: Vec<u8> = Vec::new();
1859 let (mut q, ql) = pi_current_char_recover(ctxt);
1860 if q == 0 {
1861 pi_fatal_err(ctxt, XML_ERR_COMMENT_NOT_FINISHED);
1862 return;
1863 }
1864 pi_nextl(ctxt, ql);
1865 let (mut r, rl) = pi_current_char_recover(ctxt);
1866 if r == 0 {
1867 pi_fatal_err(ctxt, XML_ERR_COMMENT_NOT_FINISHED);
1868 return;
1869 }
1870 pi_nextl(ctxt, rl);
1871 let (mut cur, mut l) = pi_current_char_recover(ctxt);
1872 while pi_is_char(cur) && !(cur == b'>' as c_int && r == b'-' as c_int && q == b'-' as c_int)
1873 {
1874 if r == b'-' as c_int && q == b'-' as c_int {
1875 pi_fatal_err(ctxt, XML_ERR_HYPHEN_IN_COMMENT);
1876 }
1877 pi_push_codepoint(&mut buf, q);
1878 q = r;
1879 r = cur;
1880 pi_nextl(ctxt, l);
1881 let (c2, l2) = pi_current_char_recover(ctxt);
1882 cur = c2;
1883 l = l2;
1884 }
1885 if cur == 0 {
1886 pi_fatal_err(ctxt, XML_ERR_COMMENT_NOT_FINISHED);
1887 return;
1888 }
1889 if !pi_is_char(cur) {
1890 pi_fatal_err(ctxt, XML_ERR_INVALID_CHAR);
1891 return;
1892 }
1893 pi_next1(ctxt);
1894 pi_sax_comment(ctxt, &buf);
1895 }
1896}
1897
1898unsafe fn pi_parse_char_data(ctxt: *mut _xmlParserCtxt, _cdata: c_int) {
1900 unsafe {
1901 let mut buf: Vec<u8> = Vec::new();
1902 loop {
1903 if pi_stopped(ctxt) {
1904 break;
1905 }
1906 let input = pi_input(ctxt);
1907 if input.is_null() {
1908 break;
1909 }
1910 if (*input).cur >= (*input).end {
1911 break;
1912 }
1913 let c = pi_raw(ctxt);
1914 if c == b'<' || c == b'&' {
1915 break;
1916 }
1917 buf.push(c);
1918 pi_next1(ctxt);
1919 }
1920 if buf.is_empty() {
1921 return;
1922 }
1923 let all_ws = buf.iter().all(|&b| pi_is_blank_ch(b));
1925 let keep_blanks = (*ctxt).keepBlanks != 0;
1926 let ignorable = all_ws && !keep_blanks;
1927 pi_sax_chars(ctxt, &buf, ignorable);
1928 }
1929}
1930
1931unsafe fn pi_parse_cd_sect(ctxt: *mut _xmlParserCtxt) {
1933 unsafe {
1934 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' || pi_nxt(ctxt, 2) != b'[' {
1935 return;
1936 }
1937 pi_skip(ctxt, 3);
1938 if !pi_cmp6(ctxt, b"CDATA[") {
1939 return;
1940 }
1941 pi_skip(ctxt, 6);
1942
1943 let mut buf: Vec<u8> = Vec::new();
1944 let (mut r, rl) = pi_current_char_recover(ctxt);
1945 if !pi_is_char(r) {
1946 pi_fatal_err(ctxt, XML_ERR_CDATA_NOT_FINISHED);
1947 return;
1948 }
1949 pi_nextl(ctxt, rl);
1950 let (mut s, sl) = pi_current_char_recover(ctxt);
1951 if !pi_is_char(s) {
1952 pi_fatal_err(ctxt, XML_ERR_CDATA_NOT_FINISHED);
1953 return;
1954 }
1955 pi_nextl(ctxt, sl);
1956 let (mut cur, mut l) = pi_current_char_recover(ctxt);
1957 while pi_is_char(cur) && !(r == b']' as c_int && s == b']' as c_int && cur == b'>' as c_int)
1958 {
1959 pi_push_codepoint(&mut buf, r);
1960 r = s;
1961 s = cur;
1962 pi_nextl(ctxt, l);
1963 let (c2, l2) = pi_current_char_recover(ctxt);
1964 cur = c2;
1965 l = l2;
1966 }
1967 if cur != b'>' as c_int {
1968 pi_fatal_err(ctxt, XML_ERR_CDATA_NOT_FINISHED);
1969 return;
1970 }
1971 pi_nextl(ctxt, l);
1972
1973 let c = &*ctxt;
1975 if !c.sax.is_null() && c.disableSAX == 0 {
1976 let buf_p = pi_strndup_bytes(buf.as_ptr(), buf.len());
1977 if !buf_p.is_null() {
1978 let sax = &*c.sax;
1979 if sax.cdataBlock.is_some() && (c.options & XML_PARSE_NOCDATA) == 0 {
1980 SaxDispatcher::cdata_block(sax, c.userData, buf_p, buf.len() as c_int);
1981 } else {
1982 SaxDispatcher::characters(sax, c.userData, buf_p, buf.len() as c_int);
1983 }
1984 xmlFreeImpl(buf_p as *mut c_void);
1985 }
1986 }
1987 }
1988}
1989
1990unsafe fn pi_parse_reference(ctxt: *mut _xmlParserCtxt) {
1992 unsafe {
1993 if pi_raw(ctxt) != b'&' {
1994 return;
1995 }
1996 if pi_nxt(ctxt, 1) == b'#' {
1998 let value = pi_parse_char_ref(ctxt);
1999 if value == 0 {
2000 return;
2001 }
2002 let mut out = Vec::new();
2003 pi_push_codepoint(&mut out, value);
2004 pi_sax_chars(ctxt, &out, false);
2005 return;
2006 }
2007
2008 let name = pi_parse_entity_ref_name(ctxt);
2010 if name.is_null() {
2011 return;
2012 }
2013 let ent = pi_lookup_general_entity(ctxt, name);
2014 if ent.is_null() {
2015 let c = &*ctxt;
2017 if c.replaceEntities == 0
2018 && !c.sax.is_null()
2019 && c.disableSAX == 0
2020 && (*c.sax).reference.is_some()
2021 {
2022 SaxDispatcher::reference(&*c.sax, c.userData, name);
2023 }
2024 xmlFreeImpl(name as *mut c_void);
2025 return;
2026 }
2027 if (*ctxt).wellFormed == 0 {
2028 xmlFreeImpl(name as *mut c_void);
2029 return;
2030 }
2031
2032 let etype = (*ent).etype;
2034 if etype == XML_INTERNAL_PREDEFINED_ENTITY as c_int {
2035 let val = (*ent).content;
2036 if !val.is_null() {
2037 let l = crate::abi::exports_xml2::xmlStrlen(val) as usize;
2038 let bytes = core::slice::from_raw_parts(val, l);
2039 pi_sax_chars(ctxt, bytes, false);
2040 }
2041 xmlFreeImpl(name as *mut c_void);
2042 return;
2043 }
2044
2045 let c = &*ctxt;
2046 if c.replaceEntities == 0 {
2047 if !c.sax.is_null() && c.disableSAX == 0 && (*c.sax).reference.is_some() {
2049 SaxDispatcher::reference(&*c.sax, c.userData, (*ent).name);
2050 }
2051 } else if etype == XML_INTERNAL_GENERAL_ENTITY as c_int && !(*ent).content.is_null() {
2052 let val = (*ent).content;
2054 let l = crate::abi::exports_xml2::xmlStrlen(val) as usize;
2055 let bytes = core::slice::from_raw_parts(val, l);
2056 pi_sax_chars(ctxt, bytes, false);
2057 }
2058 xmlFreeImpl(name as *mut c_void);
2059 }
2060}
2061
2062unsafe fn pi_parse_pe_reference(ctxt: *mut _xmlParserCtxt) {
2065 unsafe {
2066 if pi_raw(ctxt) != b'%' {
2067 return;
2068 }
2069 pi_next1(ctxt);
2070 let name = pi_parse_name(ctxt);
2071 if name.is_null() {
2072 pi_fatal_err(ctxt, XML_ERR_PEREF_NO_NAME);
2073 return;
2074 }
2075 if pi_raw(ctxt) != b';' {
2076 pi_fatal_err(ctxt, XML_ERR_PEREF_SEMICOL_MISSING);
2077 xmlFreeImpl(name as *mut c_void);
2078 return;
2079 }
2080 pi_next1(ctxt);
2081
2082 let ent = pi_lookup_parameter_entity(ctxt, name);
2083 if ent.is_null() {
2084 pi_fatal_err(ctxt, XML_ERR_UNDECLARED_ENTITY);
2085 xmlFreeImpl(name as *mut c_void);
2086 return;
2087 }
2088 (*ctxt).hasPErefs = 1;
2089
2090 if (*ent).etype == XML_INTERNAL_PARAMETER_ENTITY as c_int && !(*ent).content.is_null() {
2091 let content = (*ent).content;
2092 let clen = crate::abi::exports_xml2::xmlStrlen(content) as usize;
2093 let total = clen + 3;
2095 let buf = xmlMallocImpl(total) as *mut xmlChar;
2096 if !buf.is_null() {
2097 *buf = b' ';
2098 ptr::copy_nonoverlapping(content, buf.add(1), clen);
2099 *buf.add(clen + 1) = b' ';
2100 *buf.add(clen + 2) = 0;
2101 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
2102 if !input.is_null() {
2103 (*input).base = buf;
2104 (*input).cur = buf;
2105 (*input).end = buf.add(clen + 1);
2106 (*input).line = (*(*ctxt).input).line;
2107 (*input).col = (*(*ctxt).input).col;
2108 (*input).entity = ent;
2109 pi_input_push(ctxt, input);
2110 } else {
2111 xmlFreeImpl(buf as *mut c_void);
2112 }
2113 }
2114 }
2115 xmlFreeImpl(name as *mut c_void);
2116 }
2117}
2118
2119unsafe fn pi_parse_notation_decl(ctxt: *mut _xmlParserCtxt) {
2121 unsafe {
2122 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2123 return;
2124 }
2125 pi_skip(ctxt, 2);
2126 if pi_cmp8(ctxt, b"NOTATION") {
2127 pi_skip(ctxt, 8);
2128 if pi_skip_blanks(ctxt) == 0 {
2129 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2130 return;
2131 }
2132 let name = pi_parse_name(ctxt);
2133 if name.is_null() {
2134 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_STARTED);
2135 return;
2136 }
2137 if pi_skip_blanks(ctxt) == 0 {
2138 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2139 xmlFreeImpl(name as *mut c_void);
2140 return;
2141 }
2142 let mut pubid: *mut xmlChar = ptr::null_mut();
2143 let systemid = pi_parse_external_id(ctxt, &mut pubid, 0);
2144 pi_skip_blanks(ctxt);
2145 if pi_raw(ctxt) == b'>' {
2146 pi_next1(ctxt);
2147 let c = &*ctxt;
2148 if !c.sax.is_null() && c.disableSAX == 0 {
2149 SaxDispatcher::notation_decl(&*c.sax, c.userData, name, pubid, systemid);
2150 }
2151 } else {
2152 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_FINISHED);
2153 }
2154 if !systemid.is_null() {
2155 xmlFreeImpl(systemid as *mut c_void);
2156 }
2157 if !pubid.is_null() {
2158 xmlFreeImpl(pubid as *mut c_void);
2159 }
2160 xmlFreeImpl(name as *mut c_void);
2161 }
2162 }
2163}
2164
2165unsafe fn pi_parse_entity_decl(ctxt: *mut _xmlParserCtxt) {
2167 unsafe {
2168 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2169 return;
2170 }
2171 pi_skip(ctxt, 2);
2172 if pi_cmp6(ctxt, b"ENTITY") {
2173 pi_skip(ctxt, 6);
2174 if pi_skip_blanks(ctxt) == 0 {
2175 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2176 }
2177 let mut is_parameter = false;
2178 if pi_raw(ctxt) == b'%' {
2179 pi_next1(ctxt);
2180 if pi_skip_blanks(ctxt) == 0 {
2181 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2182 }
2183 is_parameter = true;
2184 }
2185 let name = pi_parse_name(ctxt);
2186 if name.is_null() {
2187 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2188 return;
2189 }
2190 if pi_skip_blanks(ctxt) == 0 {
2191 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2192 }
2193
2194 let mut value: *mut xmlChar = ptr::null_mut();
2195 let mut uri: *mut xmlChar = ptr::null_mut();
2196 let mut literal: *mut xmlChar = ptr::null_mut();
2197 let mut ndata: *const xmlChar = ptr::null();
2198 let mut orig: *mut xmlChar = ptr::null_mut();
2199
2200 if is_parameter {
2201 if pi_raw(ctxt) == b'"' || pi_raw(ctxt) == b'\'' {
2202 value = pi_parse_entity_value(ctxt, &mut orig);
2203 if !value.is_null() {
2204 let c = &*ctxt;
2205 if !c.sax.is_null() && c.disableSAX == 0 {
2206 SaxDispatcher::entity_decl(
2207 &*c.sax,
2208 c.userData,
2209 name,
2210 XML_INTERNAL_PARAMETER_ENTITY as c_int,
2211 ptr::null(),
2212 ptr::null(),
2213 value,
2214 );
2215 }
2216 }
2217 } else {
2218 uri = pi_parse_external_id(ctxt, &mut literal, 1);
2219 if !uri.is_null() {
2220 let c = &*ctxt;
2221 if !c.sax.is_null() && c.disableSAX == 0 {
2222 SaxDispatcher::entity_decl(
2223 &*c.sax,
2224 c.userData,
2225 name,
2226 XML_EXTERNAL_PARAMETER_ENTITY as c_int,
2227 literal,
2228 uri,
2229 ptr::null_mut(),
2230 );
2231 }
2232 }
2233 }
2234 } else {
2235 if pi_raw(ctxt) == b'"' || pi_raw(ctxt) == b'\'' {
2236 value = pi_parse_entity_value(ctxt, &mut orig);
2237 let c = &*ctxt;
2238 if !c.sax.is_null() && c.disableSAX == 0 {
2239 SaxDispatcher::entity_decl(
2240 &*c.sax,
2241 c.userData,
2242 name,
2243 XML_INTERNAL_GENERAL_ENTITY as c_int,
2244 ptr::null(),
2245 ptr::null(),
2246 value,
2247 );
2248 }
2249 } else {
2250 uri = pi_parse_external_id(ctxt, &mut literal, 1);
2251 if pi_raw(ctxt) != b'>' && pi_skip_blanks(ctxt) == 0 {
2252 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2253 }
2254 if pi_cmp5(ctxt, b"NDATA") {
2255 pi_skip(ctxt, 5);
2256 if pi_skip_blanks(ctxt) == 0 {
2257 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2258 }
2259 ndata = pi_parse_name(ctxt);
2260 let c = &*ctxt;
2261 if !c.sax.is_null() && c.disableSAX == 0 {
2262 SaxDispatcher::unparsed_entity_decl(
2263 &*c.sax, c.userData, name, literal, uri, ndata,
2264 );
2265 }
2266 if !ndata.is_null() {
2267 xmlFreeImpl(ndata as *mut c_void);
2268 }
2269 } else {
2270 let c = &*ctxt;
2271 if !c.sax.is_null() && c.disableSAX == 0 {
2272 SaxDispatcher::entity_decl(
2273 &*c.sax,
2274 c.userData,
2275 name,
2276 XML_EXTERNAL_GENERAL_PARSED_ENTITY as c_int,
2277 literal,
2278 uri,
2279 ptr::null_mut(),
2280 );
2281 }
2282 }
2283 }
2284 }
2285
2286 pi_skip_blanks(ctxt);
2287 if pi_raw(ctxt) != b'>' {
2288 pi_fatal_err(ctxt, XML_ERR_ENTITY_NOT_FINISHED);
2289 } else {
2290 pi_next1(ctxt);
2291 }
2292
2293 if !orig.is_null() {
2294 let c = &*ctxt;
2296 let mut cur: *mut _xmlEntity = ptr::null_mut();
2297 if !c.sax.is_null() {
2298 if is_parameter {
2299 if (*c.sax).getParameterEntity.is_some() {
2300 cur = SaxDispatcher::get_parameter_entity(&*c.sax, c.userData, name);
2301 }
2302 } else if (*c.sax).getEntity.is_some() {
2303 cur = SaxDispatcher::get_entity(&*c.sax, c.userData, name);
2304 }
2305 }
2306 if !cur.is_null() && (*cur).orig.is_null() {
2307 (*cur).orig = orig;
2308 orig = ptr::null_mut();
2309 }
2310 }
2311
2312 if !value.is_null() {
2313 xmlFreeImpl(value as *mut c_void);
2314 }
2315 if !uri.is_null() {
2316 xmlFreeImpl(uri as *mut c_void);
2317 }
2318 if !literal.is_null() {
2319 xmlFreeImpl(literal as *mut c_void);
2320 }
2321 if !orig.is_null() {
2322 xmlFreeImpl(orig as *mut c_void);
2323 }
2324 xmlFreeImpl(name as *mut c_void);
2325 }
2326 }
2327}
2328
2329unsafe fn pi_parse_default_decl(ctxt: *mut _xmlParserCtxt, value: *mut *mut xmlChar) -> c_int {
2331 unsafe {
2332 *value = ptr::null_mut();
2333 if pi_cmp9(ctxt, b"#REQUIRED") {
2334 pi_skip(ctxt, 9);
2335 return XML_ATTRIBUTE_REQUIRED;
2336 }
2337 if pi_cmp8(ctxt, b"#IMPLIED") {
2338 pi_skip(ctxt, 8);
2339 return XML_ATTRIBUTE_IMPLIED;
2340 }
2341 let mut val = XML_ATTRIBUTE_NONE;
2342 if pi_cmp6(ctxt, b"#FIXED") {
2343 pi_skip(ctxt, 6);
2344 val = XML_ATTRIBUTE_FIXED;
2345 if pi_skip_blanks(ctxt) == 0 {
2346 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2347 }
2348 }
2349 let ret = pi_parse_att_value(ctxt);
2350 if ret.is_null() {
2351 pi_fatal_err(ctxt, (*ctxt).errNo);
2352 } else {
2353 *value = ret;
2354 }
2355 val
2356 }
2357}
2358
2359unsafe fn pi_parse_attribute_type(
2361 ctxt: *mut _xmlParserCtxt,
2362 tree: *mut *mut _xmlEnumeration,
2363) -> c_int {
2364 unsafe {
2365 if pi_cmp5(ctxt, b"CDATA") {
2366 pi_skip(ctxt, 5);
2367 XML_ATTRIBUTE_CDATA
2368 } else if pi_cmp6(ctxt, b"IDREFS") {
2369 pi_skip(ctxt, 6);
2370 XML_ATTRIBUTE_IDREFS
2371 } else if pi_cmp5(ctxt, b"IDREF") {
2372 pi_skip(ctxt, 5);
2373 XML_ATTRIBUTE_IDREF
2374 } else if pi_raw(ctxt) == b'I' && pi_nxt(ctxt, 1) == b'D' {
2375 pi_skip(ctxt, 2);
2376 XML_ATTRIBUTE_ID
2377 } else if pi_cmp6(ctxt, b"ENTITY") {
2378 pi_skip(ctxt, 6);
2379 XML_ATTRIBUTE_ENTITY
2380 } else if pi_cmp8(ctxt, b"ENTITIES") {
2381 pi_skip(ctxt, 8);
2382 XML_ATTRIBUTE_ENTITIES
2383 } else if pi_cmp8(ctxt, b"NMTOKENS") {
2384 pi_skip(ctxt, 8);
2385 XML_ATTRIBUTE_NMTOKENS
2386 } else if pi_cmp7(ctxt, b"NMTOKEN") {
2387 pi_skip(ctxt, 7);
2388 XML_ATTRIBUTE_NMTOKEN
2389 } else {
2390 pi_parse_enumerated_type(ctxt, tree)
2391 }
2392 }
2393}
2394
2395unsafe fn pi_parse_notation_type(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
2397 unsafe {
2398 if pi_raw(ctxt) != b'(' {
2399 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_STARTED);
2400 return ptr::null_mut();
2401 }
2402 let mut ret: *mut _xmlEnumeration = ptr::null_mut();
2403 let mut last: *mut _xmlEnumeration = ptr::null_mut();
2404 loop {
2405 pi_next1(ctxt);
2406 pi_skip_blanks(ctxt);
2407 let name = pi_parse_name(ctxt);
2408 if name.is_null() {
2409 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2410 pi_free_enumeration(ret);
2411 return ptr::null_mut();
2412 }
2413 let cur = pi_create_enumeration(name);
2414 if cur.is_null() {
2416 pi_err_memory(ctxt);
2417 xmlFreeImpl(name as *mut c_void);
2418 pi_free_enumeration(ret);
2419 return ptr::null_mut();
2420 }
2421 if last.is_null() {
2422 ret = cur;
2423 } else {
2424 (*last).next = cur;
2425 }
2426 last = cur;
2427 pi_skip_blanks(ctxt);
2428 if pi_raw(ctxt) != b'|' {
2429 break;
2430 }
2431 }
2432 if pi_raw(ctxt) != b')' {
2433 pi_fatal_err(ctxt, XML_ERR_NOTATION_NOT_FINISHED);
2434 pi_free_enumeration(ret);
2435 return ptr::null_mut();
2436 }
2437 pi_next1(ctxt);
2438 ret
2439 }
2440}
2441
2442unsafe fn pi_parse_enumeration_type(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
2444 unsafe {
2445 if pi_raw(ctxt) != b'(' {
2446 pi_fatal_err(ctxt, XML_ERR_ATTLIST_NOT_STARTED);
2447 return ptr::null_mut();
2448 }
2449 let mut ret: *mut _xmlEnumeration = ptr::null_mut();
2450 let mut last: *mut _xmlEnumeration = ptr::null_mut();
2451 loop {
2452 pi_next1(ctxt);
2453 pi_skip_blanks(ctxt);
2454 let name = pi_parse_nmtoken(ctxt);
2455 if name.is_null() {
2456 pi_fatal_err(ctxt, XML_ERR_NMTOKEN_REQUIRED);
2457 return ret;
2458 }
2459 let cur = pi_create_enumeration(name);
2460 if cur.is_null() {
2462 pi_err_memory(ctxt);
2463 xmlFreeImpl(name as *mut c_void);
2464 pi_free_enumeration(ret);
2465 return ptr::null_mut();
2466 }
2467 if last.is_null() {
2468 ret = cur;
2469 } else {
2470 (*last).next = cur;
2471 }
2472 last = cur;
2473 pi_skip_blanks(ctxt);
2474 if pi_raw(ctxt) != b'|' {
2475 break;
2476 }
2477 }
2478 if pi_raw(ctxt) != b')' {
2479 pi_fatal_err(ctxt, XML_ERR_ATTLIST_NOT_FINISHED);
2480 return ret;
2481 }
2482 pi_next1(ctxt);
2483 ret
2484 }
2485}
2486
2487unsafe fn pi_parse_enumerated_type(
2489 ctxt: *mut _xmlParserCtxt,
2490 tree: *mut *mut _xmlEnumeration,
2491) -> c_int {
2492 unsafe {
2493 if pi_cmp8(ctxt, b"NOTATION") {
2494 pi_skip(ctxt, 8);
2495 if pi_skip_blanks(ctxt) == 0 {
2496 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2497 return 0;
2498 }
2499 *tree = pi_parse_notation_type(ctxt);
2500 if tree.is_null() || (*tree).is_null() {
2501 return 0;
2502 }
2503 return XML_ATTRIBUTE_NOTATION;
2504 }
2505 *tree = pi_parse_enumeration_type(ctxt);
2506 if tree.is_null() || (*tree).is_null() {
2507 return 0;
2508 }
2509 XML_ATTRIBUTE_ENUMERATION
2510 }
2511}
2512
2513unsafe fn pi_parse_attribute_list_decl(ctxt: *mut _xmlParserCtxt) {
2515 unsafe {
2516 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2517 return;
2518 }
2519 pi_skip(ctxt, 2);
2520 if pi_cmp7(ctxt, b"ATTLIST") {
2521 pi_skip(ctxt, 7);
2522 if pi_skip_blanks(ctxt) == 0 {
2523 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2524 }
2525 let elem_name = pi_parse_name(ctxt);
2526 if elem_name.is_null() {
2527 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2528 return;
2529 }
2530 pi_skip_blanks(ctxt);
2531 while pi_raw(ctxt) != b'>' && !pi_stopped(ctxt) {
2532 let mut tree: *mut _xmlEnumeration = ptr::null_mut();
2533 let attr_name = pi_parse_name(ctxt);
2534 if attr_name.is_null() {
2535 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2536 break;
2537 }
2538 if pi_skip_blanks(ctxt) == 0 {
2539 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2540 xmlFreeImpl(attr_name as *mut c_void);
2541 break;
2542 }
2543 let type_ = pi_parse_attribute_type(ctxt, &mut tree);
2544 if type_ <= 0 {
2545 xmlFreeImpl(attr_name as *mut c_void);
2546 break;
2547 }
2548 if pi_skip_blanks(ctxt) == 0 {
2549 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2550 if !tree.is_null() {
2551 pi_free_enumeration(tree);
2552 }
2553 xmlFreeImpl(attr_name as *mut c_void);
2554 break;
2555 }
2556 let mut default_value: *mut xmlChar = ptr::null_mut();
2557 let def = pi_parse_default_decl(ctxt, &mut default_value);
2558 if def <= 0 {
2559 if !default_value.is_null() {
2560 xmlFreeImpl(default_value as *mut c_void);
2561 }
2562 if !tree.is_null() {
2563 pi_free_enumeration(tree);
2564 }
2565 xmlFreeImpl(attr_name as *mut c_void);
2566 break;
2567 }
2568 if pi_raw(ctxt) != b'>' && pi_skip_blanks(ctxt) == 0 {
2569 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2570 if !default_value.is_null() {
2571 xmlFreeImpl(default_value as *mut c_void);
2572 }
2573 if !tree.is_null() {
2574 pi_free_enumeration(tree);
2575 }
2576 xmlFreeImpl(attr_name as *mut c_void);
2577 break;
2578 }
2579 let c = &*ctxt;
2580 if !c.sax.is_null() && c.disableSAX == 0 {
2581 SaxDispatcher::attribute_decl(
2582 &*c.sax,
2583 c.userData,
2584 elem_name,
2585 attr_name,
2586 type_,
2587 def,
2588 default_value,
2589 tree,
2590 );
2591 } else if !tree.is_null() {
2592 pi_free_enumeration(tree);
2593 }
2594 if !default_value.is_null() {
2595 xmlFreeImpl(default_value as *mut c_void);
2596 }
2597 xmlFreeImpl(attr_name as *mut c_void);
2598 }
2599 if pi_raw(ctxt) == b'>' {
2600 pi_next1(ctxt);
2601 }
2602 xmlFreeImpl(elem_name as *mut c_void);
2603 }
2604 }
2605}
2606
2607unsafe fn pi_create_enumeration(name: *const xmlChar) -> *mut _xmlEnumeration {
2609 unsafe {
2610 let cur = xmlMallocZero(size_of::<_xmlEnumeration>()) as *mut _xmlEnumeration;
2611 if !cur.is_null() {
2612 (*cur).name = name;
2613 (*cur).next = ptr::null_mut();
2614 }
2615 cur
2616 }
2617}
2618
2619unsafe fn pi_free_enumeration(cur: *mut _xmlEnumeration) {
2621 unsafe {
2622 let mut cur = cur;
2623 while !cur.is_null() {
2624 let next = (*cur).next;
2625 if !(*cur).name.is_null() {
2626 xmlFreeImpl((*cur).name as *mut c_void);
2627 }
2628 xmlFreeImpl(cur as *mut c_void);
2629 cur = next;
2630 }
2631 }
2632}
2633
2634unsafe fn pi_parse_element_mixed_content_decl(
2636 ctxt: *mut _xmlParserCtxt,
2637 _open_input_nr: c_int,
2638) -> *mut _xmlElementContent {
2639 unsafe {
2640 if pi_cmp7(ctxt, b"#PCDATA") {
2641 pi_skip(ctxt, 7);
2642 pi_skip_blanks(ctxt);
2643 if pi_raw(ctxt) == b')' {
2644 pi_next1(ctxt);
2645 let ret = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2646 if pi_raw(ctxt) == b'*' {
2647 if !ret.is_null() {
2648 (*ret).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2649 }
2650 pi_next1(ctxt);
2651 }
2652 return ret;
2653 }
2654 let mut ret: *mut _xmlElementContent =
2655 create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2656 let mut cur = ret;
2657 let mut elem: *const xmlChar = ptr::null();
2658 while pi_raw(ctxt) == b'|' && !pi_stopped(ctxt) {
2659 pi_next1(ctxt);
2660 let n = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
2661 if n.is_null() {
2662 pi_err_memory(ctxt);
2663 free_content_model(ret);
2664 return ptr::null_mut();
2665 }
2666 if elem.is_null() {
2667 (*n).c1 = cur;
2668 if !cur.is_null() {
2669 (*cur).parent = n;
2670 }
2671 ret = n;
2672 cur = n;
2673 } else {
2674 (*cur).c2 = n;
2675 (*n).parent = cur;
2676 let c1 = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2677 xmlFreeImpl(elem as *mut c_void);
2678 (*n).c1 = c1;
2679 if !c1.is_null() {
2680 (*c1).parent = n;
2681 }
2682 cur = n;
2683 }
2684 pi_skip_blanks(ctxt);
2685 elem = pi_parse_name(ctxt);
2686 if elem.is_null() {
2687 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2688 free_content_model(ret);
2689 return ptr::null_mut();
2690 }
2691 pi_skip_blanks(ctxt);
2692 }
2693 if pi_raw(ctxt) == b')' && pi_nxt(ctxt, 1) == b'*' {
2694 if !elem.is_null() {
2695 let c2 = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2696 xmlFreeImpl(elem as *mut c_void);
2697 if !cur.is_null() {
2698 (*cur).c2 = c2;
2699 if !c2.is_null() {
2700 (*c2).parent = cur;
2701 }
2702 }
2703 }
2704 if !ret.is_null() {
2705 (*ret).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2706 }
2707 pi_skip(ctxt, 2);
2708 } else {
2709 if !elem.is_null() {
2710 xmlFreeImpl(elem as *mut c_void);
2711 }
2712 free_content_model(ret);
2713 pi_fatal_err(ctxt, XML_ERR_MIXED_NOT_STARTED);
2714 return ptr::null_mut();
2715 }
2716 return ret;
2717 }
2718 pi_fatal_err(ctxt, XML_ERR_PCDATA_REQUIRED);
2719 ptr::null_mut()
2720 }
2721}
2722
2723unsafe fn pi_parse_element_children_content_decl_priv(
2725 ctxt: *mut _xmlParserCtxt,
2726 _open_input_nr: c_int,
2727 depth: c_int,
2728) -> *mut _xmlElementContent {
2729 unsafe {
2730 let max_depth = if (*ctxt).options & XML_PARSE_HUGE != 0 {
2731 2048
2732 } else {
2733 256
2734 };
2735 if depth > max_depth {
2736 pi_fatal_err(ctxt, XML_ERR_RESOURCE_LIMIT);
2737 return ptr::null_mut();
2738 }
2739 pi_skip_blanks(ctxt);
2740 let mut ret: *mut _xmlElementContent = ptr::null_mut();
2741 let mut cur: *mut _xmlElementContent = ptr::null_mut();
2742 let mut last: *mut _xmlElementContent = ptr::null_mut();
2743 let mut type_: u8 = 0;
2744
2745 if pi_raw(ctxt) == b'(' {
2746 pi_next1(ctxt);
2747 cur = pi_parse_element_children_content_decl_priv(ctxt, (*ctxt).inputNr, depth + 1);
2748 if cur.is_null() {
2749 return ptr::null_mut();
2750 }
2751 ret = cur;
2752 } else {
2753 let elem = pi_parse_name(ctxt);
2754 if elem.is_null() {
2755 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2756 return ptr::null_mut();
2757 }
2758 cur = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2759 xmlFreeImpl(elem as *mut c_void);
2760 if cur.is_null() {
2761 pi_err_memory(ctxt);
2762 return ptr::null_mut();
2763 }
2764 ret = cur;
2765 if pi_raw(ctxt) == b'?' {
2766 (*cur).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2767 pi_next1(ctxt);
2768 } else if pi_raw(ctxt) == b'*' {
2769 (*cur).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2770 pi_next1(ctxt);
2771 } else if pi_raw(ctxt) == b'+' {
2772 (*cur).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2773 pi_next1(ctxt);
2774 } else {
2775 (*cur).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
2776 }
2777 }
2778
2779 while !pi_stopped(ctxt) {
2780 pi_skip_blanks(ctxt);
2781 if pi_raw(ctxt) == b')' {
2782 break;
2783 }
2784 if pi_raw(ctxt) == b',' || pi_raw(ctxt) == b'|' {
2785 let sep = pi_raw(ctxt);
2786 if type_ == 0 {
2787 type_ = sep;
2788 } else if type_ != sep {
2789 pi_fatal_err(ctxt, XML_ERR_SEPARATOR_REQUIRED);
2790 free_content_model(ret);
2791 return ptr::null_mut();
2792 }
2793 pi_next1(ctxt);
2794 let op_type = if sep == b',' {
2795 XML_ELEMENT_CONTENT_SEQ as c_int
2796 } else {
2797 XML_ELEMENT_CONTENT_OR as c_int
2798 };
2799 let op = create_content_model(ptr::null(), op_type);
2800 if op.is_null() {
2801 pi_err_memory(ctxt);
2802 free_content_model(ret);
2803 return ptr::null_mut();
2804 }
2805 if last.is_null() {
2806 (*op).c1 = ret;
2807 if !ret.is_null() {
2808 (*ret).parent = op;
2809 }
2810 ret = op;
2811 cur = op;
2812 } else {
2813 (*cur).c2 = op;
2814 (*op).parent = cur;
2815 (*op).c1 = last;
2816 if !last.is_null() {
2817 (*last).parent = op;
2818 }
2819 cur = op;
2820 last = ptr::null_mut();
2821 }
2822 } else {
2823 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED);
2824 free_content_model(ret);
2825 return ptr::null_mut();
2826 }
2827
2828 pi_skip_blanks(ctxt);
2829 if pi_raw(ctxt) == b'(' {
2830 pi_next1(ctxt);
2831 last =
2832 pi_parse_element_children_content_decl_priv(ctxt, (*ctxt).inputNr, depth + 1);
2833 if last.is_null() {
2834 free_content_model(ret);
2835 return ptr::null_mut();
2836 }
2837 } else {
2838 let elem = pi_parse_name(ctxt);
2839 if elem.is_null() {
2840 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2841 free_content_model(ret);
2842 return ptr::null_mut();
2843 }
2844 last = create_content_model(elem, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2845 xmlFreeImpl(elem as *mut c_void);
2846 if last.is_null() {
2847 pi_err_memory(ctxt);
2848 free_content_model(ret);
2849 return ptr::null_mut();
2850 }
2851 if pi_raw(ctxt) == b'?' {
2852 (*last).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2853 pi_next1(ctxt);
2854 } else if pi_raw(ctxt) == b'*' {
2855 (*last).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2856 pi_next1(ctxt);
2857 } else if pi_raw(ctxt) == b'+' {
2858 (*last).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2859 pi_next1(ctxt);
2860 } else {
2861 (*last).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
2862 }
2863 }
2864 }
2865
2866 if !cur.is_null() && !last.is_null() {
2867 (*cur).c2 = last;
2868 (*last).parent = cur;
2869 }
2870 pi_next1(ctxt);
2871 if pi_raw(ctxt) == b'?' {
2872 if !ret.is_null() {
2873 (*ret).ocur = if (*ret).ocur == XML_ELEMENT_CONTENT_PLUS as c_int
2874 || (*ret).ocur == XML_ELEMENT_CONTENT_MULT as c_int
2875 {
2876 XML_ELEMENT_CONTENT_MULT as c_int
2877 } else {
2878 XML_ELEMENT_CONTENT_OPT as c_int
2879 };
2880 }
2881 pi_next1(ctxt);
2882 } else if pi_raw(ctxt) == b'*' {
2883 if !ret.is_null() {
2884 (*ret).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2885 }
2886 pi_next1(ctxt);
2887 } else if pi_raw(ctxt) == b'+' {
2888 if !ret.is_null() {
2889 (*ret).ocur = if (*ret).ocur == XML_ELEMENT_CONTENT_OPT as c_int
2890 || (*ret).ocur == XML_ELEMENT_CONTENT_MULT as c_int
2891 {
2892 XML_ELEMENT_CONTENT_MULT as c_int
2893 } else {
2894 XML_ELEMENT_CONTENT_PLUS as c_int
2895 };
2896 }
2897 pi_next1(ctxt);
2898 }
2899 ret
2900 }
2901}
2902
2903unsafe fn pi_parse_element_content_decl(
2905 ctxt: *mut _xmlParserCtxt,
2906 name: *const xmlChar,
2907 result: *mut *mut _xmlElementContent,
2908) -> c_int {
2909 unsafe {
2910 *result = ptr::null_mut();
2911 if pi_raw(ctxt) != b'(' {
2912 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2913 return -1;
2914 }
2915 let open_input_nr = (*ctxt).inputNr;
2916 pi_next1(ctxt);
2917 pi_skip_blanks(ctxt);
2918
2919 let (tree, res) = if pi_cmp7(ctxt, b"#PCDATA") {
2920 (
2921 pi_parse_element_mixed_content_decl(ctxt, open_input_nr),
2922 XML_ELEMENT_TYPE_MIXED,
2923 )
2924 } else {
2925 (
2926 pi_parse_element_children_content_decl_priv(ctxt, open_input_nr, 1),
2927 XML_ELEMENT_TYPE_ELEMENT,
2928 )
2929 };
2930 if tree.is_null() {
2931 return -1;
2932 }
2933 pi_skip_blanks(ctxt);
2934 *result = tree;
2935 res
2936 }
2937}
2938
2939unsafe fn pi_parse_element_decl(ctxt: *mut _xmlParserCtxt) -> c_int {
2941 unsafe {
2942 let mut ret = -1;
2943 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'!' {
2944 return ret;
2945 }
2946 pi_skip(ctxt, 2);
2947 if pi_cmp7(ctxt, b"ELEMENT") {
2948 pi_skip(ctxt, 7);
2949 if pi_skip_blanks(ctxt) == 0 {
2950 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2951 return -1;
2952 }
2953 let name = pi_parse_name(ctxt);
2954 if name.is_null() {
2955 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
2956 return -1;
2957 }
2958 if pi_skip_blanks(ctxt) == 0 {
2959 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
2960 }
2961 let mut content: *mut _xmlElementContent = ptr::null_mut();
2962 if pi_cmp5(ctxt, b"EMPTY") {
2963 pi_skip(ctxt, 5);
2964 ret = XML_ELEMENT_TYPE_EMPTY;
2965 } else if pi_raw(ctxt) == b'A' && pi_nxt(ctxt, 1) == b'N' && pi_nxt(ctxt, 2) == b'Y' {
2966 pi_skip(ctxt, 3);
2967 ret = XML_ELEMENT_TYPE_ANY;
2968 } else if pi_raw(ctxt) == b'(' {
2969 ret = pi_parse_element_content_decl(ctxt, name, &mut content);
2970 if ret <= 0 {
2971 xmlFreeImpl(name as *mut c_void);
2972 return -1;
2973 }
2974 } else {
2975 pi_fatal_err(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED);
2976 xmlFreeImpl(name as *mut c_void);
2977 return -1;
2978 }
2979
2980 pi_skip_blanks(ctxt);
2981 if pi_raw(ctxt) != b'>' {
2982 pi_fatal_err(ctxt, XML_ERR_GT_REQUIRED);
2983 if !content.is_null() {
2984 free_content_model(content);
2985 }
2986 } else {
2987 pi_next1(ctxt);
2988 let c = &*ctxt;
2989 if !c.sax.is_null() && c.disableSAX == 0 && (*c.sax).elementDecl.is_some() {
2990 if !content.is_null() {
2991 (*content).parent = ptr::null_mut();
2992 }
2993 SaxDispatcher::element_decl(&*c.sax, c.userData, name, ret, content);
2994 if !content.is_null() && (*content).parent.is_null() {
2995 free_content_model(content);
2997 }
2998 } else if !content.is_null() {
2999 free_content_model(content);
3000 }
3001 }
3002 xmlFreeImpl(name as *mut c_void);
3003 }
3004 ret
3005 }
3006}
3007
3008unsafe fn pi_parse_markup_decl(ctxt: *mut _xmlParserCtxt) {
3010 unsafe {
3011 if pi_raw(ctxt) == b'<' {
3012 if pi_nxt(ctxt, 1) == b'!' {
3013 match pi_nxt(ctxt, 2) {
3014 b'E' => {
3015 if pi_nxt(ctxt, 3) == b'L' {
3016 pi_parse_element_decl(ctxt);
3017 } else if pi_nxt(ctxt, 3) == b'N' {
3018 pi_parse_entity_decl(ctxt);
3019 } else {
3020 pi_skip(ctxt, 2);
3021 }
3022 }
3023 b'A' => pi_parse_attribute_list_decl(ctxt),
3024 b'N' => pi_parse_notation_decl(ctxt),
3025 b'-' => pi_parse_comment(ctxt),
3026 _ => {
3027 pi_fatal_err(
3028 ctxt,
3029 if (*ctxt).inSubset == 2 {
3030 XML_ERR_EXT_SUBSET_NOT_FINISHED
3031 } else {
3032 XML_ERR_INT_SUBSET_NOT_FINISHED
3033 },
3034 );
3035 pi_skip(ctxt, 2);
3036 }
3037 }
3038 } else if pi_nxt(ctxt, 1) == b'?' {
3039 pi_parse_pi(ctxt);
3040 }
3041 }
3042 }
3043}
3044
3045unsafe fn pi_parse_text_decl(ctxt: *mut _xmlParserCtxt) {
3047 unsafe {
3048 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
3049 pi_skip(ctxt, 5);
3050 } else {
3051 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_STARTED);
3052 return;
3053 }
3054 if pi_skip_blanks(ctxt) == 0 {
3055 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3056 }
3057 let mut version = pi_parse_version_info(ctxt);
3058 if version.is_null() {
3059 version = crate::abi::exports_xml2::xmlStrdup(c"1.0".as_ptr() as *const xmlChar);
3060 } else if pi_skip_blanks(ctxt) == 0 {
3061 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3062 }
3063 let input = pi_input(ctxt);
3064 if !input.is_null() {
3065 (*input).version = version;
3066 } else if !version.is_null() {
3067 xmlFreeImpl(version as *mut c_void);
3068 }
3069 pi_parse_encoding_decl(ctxt);
3070 pi_skip_blanks(ctxt);
3071 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3072 pi_skip(ctxt, 2);
3073 } else if pi_raw(ctxt) == b'>' {
3074 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
3075 pi_next1(ctxt);
3076 } else {
3077 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
3078 while !pi_stopped(ctxt) && pi_raw(ctxt) != 0 {
3079 let c = pi_raw(ctxt);
3080 pi_next1(ctxt);
3081 if c == b'>' {
3082 break;
3083 }
3084 }
3085 }
3086 }
3087}
3088
3089#[allow(clippy::while_immutable_condition)]
3091unsafe fn pi_parse_external_subset(
3092 ctxt: *mut _xmlParserCtxt,
3093 public_id: *const xmlChar,
3094 system_id: *const xmlChar,
3095) {
3096 unsafe {
3097 pi_ctxt_late_init(ctxt);
3098 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
3099 pi_parse_text_decl(ctxt);
3100 }
3101 if (*ctxt).myDoc.is_null() {
3102 (*ctxt).myDoc = crate::xml::tree::new_doc(c"1.0".as_ptr() as *const xmlChar);
3103 if (*ctxt).myDoc.is_null() {
3104 pi_err_memory(ctxt);
3105 return;
3106 }
3107 (*(*ctxt).myDoc).properties |= XML_DOC_INTERNAL as c_int;
3108 }
3109 if (*(*ctxt).myDoc).intSubset.is_null() {
3110 create_int_subset((*ctxt).myDoc, ptr::null(), public_id, system_id);
3111 }
3112 (*ctxt).inSubset = 2;
3113 let old_input_nr = (*ctxt).inputNr;
3114 pi_skip_blanks(ctxt);
3115 while !pi_stopped(ctxt) {
3116 let input = pi_input(ctxt);
3117 if input.is_null() {
3118 break;
3119 }
3120 if (*input).cur >= (*input).end {
3121 if (*ctxt).inputNr <= old_input_nr {
3122 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3123 break;
3124 }
3125 pi_pop_pe(ctxt);
3126 } else if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'!' && pi_nxt(ctxt, 2) == b'[' {
3127 pi_parse_conditional_sections(ctxt);
3128 } else if pi_raw(ctxt) == b'<' && (pi_nxt(ctxt, 1) == b'!' || pi_nxt(ctxt, 1) == b'?') {
3129 pi_parse_markup_decl(ctxt);
3130 } else if pi_raw(ctxt) == b'%' {
3131 pi_parse_pe_reference(ctxt);
3132 } else {
3133 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3134 while (*ctxt).inputNr > old_input_nr {
3135 pi_pop_pe(ctxt);
3136 }
3137 break;
3138 }
3139 pi_skip_blanks(ctxt);
3140 }
3141 }
3142}
3143
3144unsafe fn pi_parse_conditional_sections(ctxt: *mut _xmlParserCtxt) {
3146 unsafe {
3147 let old_input_nr = (*ctxt).inputNr;
3148 let mut depth: usize = 0;
3149 loop {
3150 if pi_stopped(ctxt) {
3151 return;
3152 }
3153 let input = pi_input(ctxt);
3154 if input.is_null() {
3155 return;
3156 }
3157 if (*input).cur >= (*input).end {
3158 if (*ctxt).inputNr <= old_input_nr {
3159 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3160 return;
3161 }
3162 pi_pop_pe(ctxt);
3163 } else if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'!' && pi_nxt(ctxt, 2) == b'[' {
3164 pi_skip(ctxt, 3);
3165 pi_skip_blanks(ctxt);
3166 if pi_cmp7(ctxt, b"INCLUDE") {
3167 pi_skip(ctxt, 7);
3168 pi_skip_blanks(ctxt);
3169 if pi_raw(ctxt) != b'[' {
3170 pi_fatal_err(ctxt, XML_ERR_CONDSEC_INVALID);
3171 return;
3172 }
3173 pi_next1(ctxt);
3174 depth += 1;
3175 } else if pi_cmp6(ctxt, b"IGNORE") {
3176 pi_skip(ctxt, 6);
3177 pi_skip_blanks(ctxt);
3178 if pi_raw(ctxt) != b'[' {
3179 pi_fatal_err(ctxt, XML_ERR_CONDSEC_INVALID);
3180 return;
3181 }
3182 pi_next1(ctxt);
3183 let mut ignore_depth: usize = 0;
3184 loop {
3185 if pi_stopped(ctxt) {
3186 return;
3187 }
3188 let inp = pi_input(ctxt);
3189 if inp.is_null() || (*inp).cur >= (*inp).end || pi_raw(ctxt) == 0 {
3190 pi_fatal_err(ctxt, XML_ERR_CONDSEC_NOT_FINISHED);
3191 return;
3192 }
3193 if pi_raw(ctxt) == b'<'
3194 && pi_nxt(ctxt, 1) == b'!'
3195 && pi_nxt(ctxt, 2) == b'['
3196 {
3197 pi_skip(ctxt, 3);
3198 ignore_depth += 1;
3199 } else if pi_raw(ctxt) == b']'
3200 && pi_nxt(ctxt, 1) == b']'
3201 && pi_nxt(ctxt, 2) == b'>'
3202 {
3203 pi_skip(ctxt, 3);
3204 if ignore_depth == 0 {
3205 break;
3206 }
3207 ignore_depth -= 1;
3208 } else {
3209 pi_next1(ctxt);
3210 }
3211 }
3212 } else {
3213 pi_fatal_err(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD);
3214 return;
3215 }
3216 } else if depth > 0
3217 && pi_raw(ctxt) == b']'
3218 && pi_nxt(ctxt, 1) == b']'
3219 && pi_nxt(ctxt, 2) == b'>'
3220 {
3221 depth -= 1;
3222 pi_skip(ctxt, 3);
3223 } else if pi_raw(ctxt) == b'<' && (pi_nxt(ctxt, 1) == b'!' || pi_nxt(ctxt, 1) == b'?') {
3224 pi_parse_markup_decl(ctxt);
3225 } else if pi_raw(ctxt) == b'%' {
3226 pi_parse_pe_reference(ctxt);
3227 } else {
3228 pi_fatal_err(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED);
3229 return;
3230 }
3231 if depth == 0 {
3232 break;
3233 }
3234 pi_skip_blanks(ctxt);
3235 }
3236 }
3237}
3238
3239unsafe fn pi_parse_version_num(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
3241 unsafe {
3242 let mut buf: Vec<u8> = Vec::new();
3243 let mut cur = pi_raw(ctxt);
3244 if !cur.is_ascii_digit() {
3245 return ptr::null_mut();
3246 }
3247 buf.push(cur);
3248 pi_next1(ctxt);
3249 cur = pi_raw(ctxt);
3250 if cur != b'.' {
3251 return ptr::null_mut();
3252 }
3253 buf.push(cur);
3254 pi_next1(ctxt);
3255 cur = pi_raw(ctxt);
3256 while cur.is_ascii_digit() {
3257 buf.push(cur);
3258 pi_next1(ctxt);
3259 cur = pi_raw(ctxt);
3260 }
3261 pi_strndup_bytes(buf.as_ptr(), buf.len())
3262 }
3263}
3264
3265unsafe fn pi_parse_version_info(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
3267 unsafe {
3268 if pi_cmp7(ctxt, b"version") {
3269 pi_skip(ctxt, 7);
3270 pi_skip_blanks(ctxt);
3271 if pi_raw(ctxt) != b'=' {
3272 pi_fatal_err(ctxt, XML_ERR_EQUAL_REQUIRED);
3273 return ptr::null_mut();
3274 }
3275 pi_next1(ctxt);
3276 pi_skip_blanks(ctxt);
3277 if pi_raw(ctxt) == b'"' {
3278 pi_next1(ctxt);
3279 let version = pi_parse_version_num(ctxt);
3280 if pi_raw(ctxt) != b'"' {
3281 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3282 } else {
3283 pi_next1(ctxt);
3284 }
3285 return version;
3286 } else if pi_raw(ctxt) == b'\'' {
3287 pi_next1(ctxt);
3288 let version = pi_parse_version_num(ctxt);
3289 if pi_raw(ctxt) != b'\'' {
3290 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3291 } else {
3292 pi_next1(ctxt);
3293 }
3294 return version;
3295 } else {
3296 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
3297 }
3298 }
3299 ptr::null_mut()
3300 }
3301}
3302
3303unsafe fn pi_parse_enc_name(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
3305 unsafe {
3306 let cur = pi_raw(ctxt);
3307 if !(cur.is_ascii_lowercase() || cur.is_ascii_uppercase()) {
3308 pi_fatal_err(ctxt, XML_ERR_ENCODING_NAME);
3309 return ptr::null_mut();
3310 }
3311 let mut buf: Vec<u8> = Vec::new();
3312 buf.push(cur);
3313 pi_next1(ctxt);
3314 let mut c = pi_raw(ctxt);
3315 while c.is_ascii_alphanumeric() || c == b'.' || c == b'_' || c == b'-' {
3316 buf.push(c);
3317 pi_next1(ctxt);
3318 c = pi_raw(ctxt);
3319 }
3320 pi_strndup_bytes(buf.as_ptr(), buf.len())
3321 }
3322}
3323
3324unsafe fn pi_parse_encoding_decl(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
3326 unsafe {
3327 pi_skip_blanks(ctxt);
3328 if !pi_cmp8(ctxt, b"encoding") {
3329 return ptr::null();
3330 }
3331 pi_skip(ctxt, 8);
3332 pi_skip_blanks(ctxt);
3333 if pi_raw(ctxt) != b'=' {
3334 pi_fatal_err(ctxt, XML_ERR_EQUAL_REQUIRED);
3335 return ptr::null();
3336 }
3337 pi_next1(ctxt);
3338 pi_skip_blanks(ctxt);
3339 let mut encoding: *mut xmlChar = ptr::null_mut();
3340 if pi_raw(ctxt) == b'"' {
3341 pi_next1(ctxt);
3342 encoding = pi_parse_enc_name(ctxt);
3343 if pi_raw(ctxt) != b'"' {
3344 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3345 if !encoding.is_null() {
3346 xmlFreeImpl(encoding as *mut c_void);
3347 }
3348 return ptr::null();
3349 }
3350 pi_next1(ctxt);
3351 } else if pi_raw(ctxt) == b'\'' {
3352 pi_next1(ctxt);
3353 encoding = pi_parse_enc_name(ctxt);
3354 if pi_raw(ctxt) != b'\'' {
3355 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3356 if !encoding.is_null() {
3357 xmlFreeImpl(encoding as *mut c_void);
3358 }
3359 return ptr::null();
3360 }
3361 pi_next1(ctxt);
3362 } else {
3363 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
3364 }
3365 if encoding.is_null() {
3366 return ptr::null();
3367 }
3368 let c = &mut *ctxt;
3369 if !c.encoding.is_null() {
3370 xmlFreeImpl(c.encoding as *mut c_void);
3371 }
3372 c.encoding = encoding;
3373 c.encoding as *const xmlChar
3374 }
3375}
3376
3377unsafe fn pi_parse_sd_decl(ctxt: *mut _xmlParserCtxt) -> c_int {
3379 unsafe {
3380 let mut standalone = -2;
3381 pi_skip_blanks(ctxt);
3382 if pi_cmp10(ctxt, b"standalone") {
3383 pi_skip(ctxt, 10);
3384 pi_skip_blanks(ctxt);
3385 if pi_raw(ctxt) != b'=' {
3386 pi_fatal_err(ctxt, XML_ERR_EQUAL_REQUIRED);
3387 return standalone;
3388 }
3389 pi_next1(ctxt);
3390 pi_skip_blanks(ctxt);
3391 let quote = pi_raw(ctxt);
3392 if quote == b'\'' || quote == b'"' {
3393 pi_next1(ctxt);
3394 if pi_raw(ctxt) == b'n' && pi_nxt(ctxt, 1) == b'o' {
3395 standalone = 0;
3396 pi_skip(ctxt, 2);
3397 } else if pi_raw(ctxt) == b'y' && pi_nxt(ctxt, 1) == b'e' && pi_nxt(ctxt, 2) == b's'
3398 {
3399 standalone = 1;
3400 pi_skip(ctxt, 3);
3401 } else {
3402 pi_fatal_err(ctxt, XML_ERR_STANDALONE_VALUE);
3403 }
3404 if pi_raw(ctxt) != quote {
3405 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_CLOSED);
3406 } else {
3407 pi_next1(ctxt);
3408 }
3409 } else {
3410 pi_fatal_err(ctxt, XML_ERR_STRING_NOT_STARTED);
3411 }
3412 }
3413 standalone
3414 }
3415}
3416
3417unsafe fn pi_parse_xml_decl(ctxt: *mut _xmlParserCtxt) {
3419 unsafe {
3420 (*ctxt).standalone = -2;
3421 pi_skip(ctxt, 5);
3422 if !pi_is_blank_ch(pi_raw(ctxt)) {
3423 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3424 }
3425 pi_skip_blanks(ctxt);
3426 let version = pi_parse_version_info(ctxt);
3427 if version.is_null() {
3428 pi_fatal_err(ctxt, XML_ERR_VERSION_MISSING);
3429 } else {
3430 if !pi_cstr_eq(version, b"1.0") {
3431 if pi_nxt(ctxt, 0) == b'1' {
3432 } else {
3434 pi_fatal_err(ctxt, XML_ERR_UNKNOWN_VERSION);
3435 }
3436 }
3437 let c = &mut *ctxt;
3438 if !c.version.is_null() {
3439 xmlFreeImpl(c.version as *mut c_void);
3440 }
3441 c.version = version;
3442 }
3443 if !pi_is_blank_ch(pi_raw(ctxt)) {
3444 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3445 pi_skip(ctxt, 2);
3446 return;
3447 }
3448 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3449 }
3450 pi_parse_encoding_decl(ctxt);
3451 if !(*ctxt).encoding.is_null() && !pi_is_blank_ch(pi_raw(ctxt)) {
3452 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3453 pi_skip(ctxt, 2);
3454 return;
3455 }
3456 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3457 }
3458 pi_skip_blanks(ctxt);
3459 (*ctxt).standalone = pi_parse_sd_decl(ctxt);
3460 pi_skip_blanks(ctxt);
3461 if pi_raw(ctxt) == b'?' && pi_nxt(ctxt, 1) == b'>' {
3462 pi_skip(ctxt, 2);
3463 } else if pi_raw(ctxt) == b'>' {
3464 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
3465 pi_next1(ctxt);
3466 } else {
3467 pi_fatal_err(ctxt, XML_ERR_XMLDECL_NOT_FINISHED);
3468 while !pi_stopped(ctxt) && pi_raw(ctxt) != 0 {
3469 let c = pi_raw(ctxt);
3470 pi_next1(ctxt);
3471 if c == b'>' {
3472 break;
3473 }
3474 }
3475 }
3476 }
3477}
3478
3479unsafe fn pi_parse_misc(ctxt: *mut _xmlParserCtxt) {
3481 unsafe {
3482 while !pi_stopped(ctxt) {
3483 pi_skip_blanks(ctxt);
3484 if pi_raw(ctxt) == b'<' && pi_nxt(ctxt, 1) == b'?' {
3485 pi_parse_pi(ctxt);
3486 } else if pi_raw(ctxt) == b'<'
3487 && pi_nxt(ctxt, 1) == b'!'
3488 && pi_nxt(ctxt, 2) == b'-'
3489 && pi_nxt(ctxt, 3) == b'-'
3490 {
3491 pi_parse_comment(ctxt);
3492 } else {
3493 break;
3494 }
3495 }
3496 }
3497}
3498
3499#[allow(clippy::while_immutable_condition)]
3501unsafe fn pi_parse_content(ctxt: *mut _xmlParserCtxt) {
3502 unsafe {
3503 if ctxt.is_null() || pi_input(ctxt).is_null() {
3504 return;
3505 }
3506 pi_ctxt_late_init(ctxt);
3507 let old_name_nr = (*ctxt).nameNr;
3508 let old_space_nr = (*ctxt).spaceNr;
3509 let old_node_nr = (*ctxt).nodeNr;
3510 loop {
3511 let input = pi_input(ctxt);
3512 if input.is_null() {
3513 break;
3514 }
3515 if (*input).cur >= (*input).end || pi_stopped(ctxt) {
3516 break;
3517 }
3518 let cur = (*input).cur;
3519 if *cur == b'<' {
3520 if cur.add(1) < (*input).end && *cur.add(1) == b'?' {
3521 pi_parse_pi(ctxt);
3522 } else if cur.add(8) < (*input).end
3523 && *cur.add(1) == b'!'
3524 && *cur.add(2) == b'['
3525 && *cur.add(3) == b'C'
3526 && *cur.add(4) == b'D'
3527 && *cur.add(5) == b'A'
3528 && *cur.add(6) == b'T'
3529 && *cur.add(7) == b'A'
3530 && *cur.add(8) == b'['
3531 {
3532 pi_parse_cd_sect(ctxt);
3533 } else if cur.add(3) < (*input).end
3534 && *cur.add(1) == b'!'
3535 && *cur.add(2) == b'-'
3536 && *cur.add(3) == b'-'
3537 {
3538 pi_parse_comment(ctxt);
3539 } else if cur.add(1) < (*input).end && *cur.add(1) == b'/' {
3540 if (*ctxt).nameNr <= old_name_nr {
3541 break;
3542 }
3543 pi_parse_end_tag(ctxt);
3544 } else {
3545 pi_parse_element(ctxt);
3546 }
3547 } else if *cur == b'&' {
3548 pi_parse_reference(ctxt);
3549 } else {
3550 pi_parse_char_data(ctxt, 0);
3551 }
3552 }
3553 if (*ctxt).nameNr > old_name_nr
3555 && !pi_input(ctxt).is_null()
3556 && (*(*ctxt).input).cur >= (*(*ctxt).input).end
3557 && (*ctxt).wellFormed != 0
3558 {
3559 pi_fatal_err(ctxt, XML_ERR_TAG_NOT_FINISHED);
3560 }
3561 while (*ctxt).nodeNr > old_node_nr {
3563 pi_node_pop(ctxt);
3564 }
3565 while (*ctxt).nameNr > old_name_nr {
3566 pi_name_pop(ctxt);
3567 }
3568 while (*ctxt).spaceNr > old_space_nr {
3569 pi_space_pop(ctxt);
3570 }
3571 }
3572}
3573
3574unsafe fn pi_parse_attribute(
3576 ctxt: *mut _xmlParserCtxt,
3577 value: *mut *mut xmlChar,
3578) -> *const xmlChar {
3579 unsafe {
3580 *value = ptr::null_mut();
3581 let name = pi_parse_name(ctxt);
3582 if name.is_null() {
3583 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
3584 return ptr::null();
3585 }
3586 pi_skip_blanks(ctxt);
3587 let mut val: *mut xmlChar = ptr::null_mut();
3588 if pi_raw(ctxt) == b'=' {
3589 pi_next1(ctxt);
3590 pi_skip_blanks(ctxt);
3591 val = pi_parse_att_value(ctxt);
3592 } else {
3593 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE);
3594 return name;
3595 }
3596 if pi_cstr_eq(name, b"xml:space") && !val.is_null() && !(*ctxt).space.is_null() {
3598 if pi_cstr_eq(val, b"default") {
3599 *(*ctxt).space = 0;
3600 } else if pi_cstr_eq(val, b"preserve") {
3601 *(*ctxt).space = 1;
3602 }
3603 }
3604 *value = val;
3605 name
3606 }
3607}
3608
3609unsafe fn pi_parse_start_tag(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
3611 unsafe {
3612 if pi_raw(ctxt) != b'<' {
3613 return ptr::null();
3614 }
3615 pi_next1(ctxt);
3616 let name = pi_parse_name(ctxt);
3617 if name.is_null() {
3618 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
3619 return ptr::null();
3620 }
3621 let c0 = &mut *ctxt;
3622 let mut atts = c0.atts;
3623 let mut maxatts = c0.maxatts;
3624 let mut nbatts: usize = 0;
3625 let mut failed = false;
3626
3627 pi_skip_blanks(ctxt);
3628 while !(pi_raw(ctxt) == b'>' || (pi_raw(ctxt) == b'/' && pi_nxt(ctxt, 1) == b'>'))
3629 && pi_is_byte_char(pi_raw(ctxt))
3630 && !pi_stopped(ctxt)
3631 {
3632 let mut attvalue: *mut xmlChar = ptr::null_mut();
3633 let attname = pi_parse_attribute(ctxt, &mut attvalue);
3634 if attname.is_null() {
3635 failed = true;
3636 if !attvalue.is_null() {
3637 xmlFreeImpl(attvalue as *mut c_void);
3638 }
3639 break;
3640 }
3641 if !attvalue.is_null() {
3642 let mut i = 0;
3644 while i < nbatts {
3645 if crate::abi::exports_xml2::xmlStrEqual(*atts.add(i), attname) != 0 {
3646 failed = true;
3647 break;
3648 }
3649 i += 2;
3650 }
3651 if failed {
3652 if !attvalue.is_null() {
3653 xmlFreeImpl(attvalue as *mut c_void);
3654 }
3655 break;
3656 }
3657 if nbatts + 4 > maxatts as usize {
3659 let new_max = if maxatts == 0 { 20 } else { maxatts * 2 };
3660 let n = xmlReallocImpl(
3661 atts as *mut c_void,
3662 (new_max as usize) * size_of::<*const xmlChar>(),
3663 ) as *mut *const xmlChar;
3664 if n.is_null() {
3665 pi_err_memory(ctxt);
3666 failed = true;
3667 xmlFreeImpl(attvalue as *mut c_void);
3668 break;
3669 }
3670 atts = n;
3671 maxatts = new_max;
3672 let c = &mut *ctxt;
3673 c.atts = atts;
3674 c.maxatts = maxatts;
3675 }
3676 *atts.add(nbatts) = attname;
3677 *atts.add(nbatts + 1) = attvalue;
3678 nbatts += 2;
3679 attvalue = ptr::null_mut();
3680 } else {
3681 failed = true;
3682 }
3683 if !attvalue.is_null() {
3684 xmlFreeImpl(attvalue as *mut c_void);
3685 }
3686 if pi_raw(ctxt) == b'>' || (pi_raw(ctxt) == b'/' && pi_nxt(ctxt, 1) == b'>') {
3687 break;
3688 }
3689 if pi_skip_blanks(ctxt) == 0 {
3690 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3691 }
3692 }
3693
3694 pi_dispatch_start_element(ctxt, name, atts, nbatts);
3696
3697 let mut i = 0;
3699 while i < nbatts {
3700 if !atts.is_null() {
3701 let p = *atts.add(i);
3702 if !p.is_null() {
3703 xmlFreeImpl(p as *mut c_void);
3704 }
3705 }
3706 i += 1;
3707 }
3708 name
3709 }
3710}
3711
3712unsafe fn pi_parse_end_tag(ctxt: *mut _xmlParserCtxt) {
3714 unsafe {
3715 if pi_raw(ctxt) != b'<' || pi_nxt(ctxt, 1) != b'/' {
3716 pi_fatal_err(ctxt, XML_ERR_LTSLASH_REQUIRED);
3717 return;
3718 }
3719 pi_skip(ctxt, 2);
3720 let c = &*ctxt;
3721 let name = pi_parse_name_and_compare(ctxt, c.name);
3722 pi_skip_blanks(ctxt);
3723 if !pi_is_byte_char(pi_raw(ctxt)) || pi_raw(ctxt) != b'>' {
3724 pi_fatal_err(ctxt, XML_ERR_GT_REQUIRED);
3725 } else {
3726 pi_next1(ctxt);
3727 }
3728 if name != std::ptr::dangling::<xmlChar>() {
3729 if name.is_null() {
3730 pi_fatal_err(ctxt, XML_ERR_TAG_NAME_MISMATCH);
3732 } else {
3733 pi_fatal_err(ctxt, XML_ERR_TAG_NAME_MISMATCH);
3734 xmlFreeImpl(name as *mut c_void);
3735 }
3736 }
3737 let c = &*ctxt;
3739 pi_dispatch_end_element(ctxt, c.name);
3740 pi_name_pop(ctxt);
3741 pi_space_pop(ctxt);
3742 }
3743}
3744
3745unsafe fn pi_parse_element(ctxt: *mut _xmlParserCtxt) {
3747 unsafe {
3748 let max_depth = if (*ctxt).options & XML_PARSE_HUGE != 0 {
3749 2048
3750 } else {
3751 256
3752 };
3753 if (*ctxt).nameNr > max_depth {
3754 pi_fatal_err(ctxt, XML_ERR_RESOURCE_LIMIT);
3755 return;
3756 }
3757 let c = &mut *ctxt;
3759 if c.spaceNr == 0 || (!c.space.is_null() && *c.space == -2) {
3760 pi_space_push(ctxt, -1);
3761 } else if !c.space.is_null() {
3762 pi_space_push(ctxt, *c.space);
3763 } else {
3764 pi_space_push(ctxt, -1);
3765 }
3766 let line = (*(*ctxt).input).line;
3767 let name = pi_parse_start_tag(ctxt);
3768 if name.is_null() {
3769 pi_space_pop(ctxt);
3770 return;
3771 }
3772 pi_name_push(ctxt, name);
3773
3774 if pi_raw(ctxt) == b'/' && pi_nxt(ctxt, 1) == b'>' {
3776 pi_skip(ctxt, 2);
3777 let c = &*ctxt;
3778 pi_dispatch_end_element(ctxt, c.name);
3779 pi_name_pop(ctxt);
3780 pi_space_pop(ctxt);
3781 return;
3782 }
3783 if pi_raw(ctxt) == b'>' {
3784 pi_next1(ctxt);
3785 } else {
3786 pi_fatal_err(ctxt, XML_ERR_GT_REQUIRED);
3787 pi_name_pop(ctxt);
3788 pi_space_pop(ctxt);
3789 return;
3790 }
3791
3792 pi_parse_content(ctxt);
3794
3795 let input = pi_input(ctxt);
3797 if input.is_null() || (*input).cur >= (*input).end {
3798 if (*ctxt).wellFormed != 0 {
3799 pi_fatal_err(ctxt, XML_ERR_TAG_NOT_FINISHED);
3800 }
3801 return;
3802 }
3803 pi_parse_end_tag(ctxt);
3804 }
3805}
3806
3807unsafe fn pi_parse_doc_type_decl(ctxt: *mut _xmlParserCtxt) {
3809 unsafe {
3810 pi_skip(ctxt, 9);
3811 if pi_skip_blanks(ctxt) == 0 {
3812 pi_fatal_err(ctxt, XML_ERR_SPACE_REQUIRED);
3813 }
3814 let name = pi_parse_name(ctxt);
3815 if name.is_null() {
3816 pi_fatal_err(ctxt, XML_ERR_NAME_REQUIRED);
3817 return;
3818 }
3819 (*ctxt).intSubName = name;
3820 pi_skip_blanks(ctxt);
3821 let mut public_id: *mut xmlChar = ptr::null_mut();
3822 let uri = pi_parse_external_id(ctxt, &mut public_id, 1);
3823 if !uri.is_null() || !public_id.is_null() {
3824 (*ctxt).hasExternalSubset = 1;
3825 }
3826 (*ctxt).extSubURI = uri;
3827 (*ctxt).extSubSystem = public_id;
3828 pi_skip_blanks(ctxt);
3829 let c = &*ctxt;
3830 if !c.sax.is_null() && c.disableSAX == 0 {
3831 SaxDispatcher::internal_subset(&*c.sax, c.userData, name, public_id, uri);
3832 }
3833 if pi_raw(ctxt) != b'[' && pi_raw(ctxt) != b'>' {
3834 pi_fatal_err(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED);
3835 }
3836 }
3837}
3838
3839#[allow(clippy::while_immutable_condition)]
3841unsafe fn pi_parse_internal_subset(ctxt: *mut _xmlParserCtxt) {
3842 unsafe {
3843 if pi_raw(ctxt) == b'[' {
3844 let old_input_nr = (*ctxt).inputNr;
3845 pi_next1(ctxt);
3846 pi_skip_blanks(ctxt);
3847 loop {
3848 if pi_stopped(ctxt) {
3849 return;
3850 }
3851 let input = pi_input(ctxt);
3852 if input.is_null() {
3853 return;
3854 }
3855 if (*input).cur >= (*input).end {
3856 if (*ctxt).inputNr <= old_input_nr {
3857 pi_fatal_err(ctxt, XML_ERR_INT_SUBSET_NOT_FINISHED);
3858 return;
3859 }
3860 pi_pop_pe(ctxt);
3861 } else if pi_raw(ctxt) == b']' && (*ctxt).inputNr <= old_input_nr {
3862 pi_next1(ctxt);
3863 pi_skip_blanks(ctxt);
3864 break;
3865 } else if pi_raw(ctxt) == b'<'
3866 && (pi_nxt(ctxt, 1) == b'!' || pi_nxt(ctxt, 1) == b'?')
3867 {
3868 pi_parse_markup_decl(ctxt);
3869 } else if pi_raw(ctxt) == b'%' {
3870 pi_parse_pe_reference(ctxt);
3871 } else {
3872 pi_fatal_err(ctxt, XML_ERR_INT_SUBSET_NOT_FINISHED);
3873 while (*ctxt).inputNr > old_input_nr {
3874 pi_pop_pe(ctxt);
3875 }
3876 return;
3877 }
3878 pi_skip_blanks(ctxt);
3879 }
3880 }
3881 if pi_raw(ctxt) != b'>' {
3882 pi_fatal_err(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED);
3883 return;
3884 }
3885 pi_next1(ctxt);
3886 }
3887}
3888
3889unsafe fn pi_parse_document(ctxt: *mut _xmlParserCtxt) -> c_int {
3891 unsafe {
3892 if ctxt.is_null() || pi_input(ctxt).is_null() {
3893 return -1;
3894 }
3895 pi_ctxt_late_init(ctxt);
3896
3897 let c0 = &*ctxt;
3899 if !c0.sax.is_null() && (*c0.sax).setDocumentLocator.is_some() {
3900 SaxDispatcher::set_document_locator(
3901 &*c0.sax,
3902 c0.userData,
3903 &crate::abi::data_globals::xmlDefaultSAXLocator as *const _xmlSAXLocator
3904 as *mut _xmlSAXLocator,
3905 );
3906 }
3907
3908 if pi_raw(ctxt) == 0 {
3909 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_EMPTY);
3910 return -1;
3911 }
3912
3913 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
3914 pi_parse_xml_decl(ctxt);
3915 pi_skip_blanks(ctxt);
3916 } else {
3917 let c = &mut *ctxt;
3918 if !c.version.is_null() {
3919 xmlFreeImpl(c.version as *mut c_void);
3920 }
3921 c.version = crate::abi::exports_xml2::xmlStrdup(c"1.0".as_ptr() as *const xmlChar);
3922 if c.version.is_null() {
3923 pi_err_memory(ctxt);
3924 return -1;
3925 }
3926 }
3927 let c1 = &*ctxt;
3928 if !c1.sax.is_null() && c1.disableSAX == 0 {
3929 SaxDispatcher::start_document(&*c1.sax, c1.userData);
3930 }
3931
3932 pi_parse_misc(ctxt);
3934
3935 if pi_cmp9(ctxt, b"<!DOCTYPE") {
3937 let c = &mut *ctxt;
3938 c.inSubset = 1;
3939 pi_parse_doc_type_decl(ctxt);
3940 if pi_raw(ctxt) == b'[' {
3941 pi_parse_internal_subset(ctxt);
3942 } else if pi_raw(ctxt) == b'>' {
3943 pi_next1(ctxt);
3944 }
3945 c.inSubset = 2;
3946 let c2 = &*ctxt;
3947 if !c2.sax.is_null() && c2.disableSAX == 0 {
3948 SaxDispatcher::external_subset(
3949 &*c2.sax,
3950 c2.userData,
3951 c2.intSubName,
3952 c2.extSubSystem,
3953 c2.extSubURI,
3954 );
3955 }
3956 let c3 = &mut *ctxt;
3957 c3.inSubset = 0;
3958 pi_parse_misc(ctxt);
3959 }
3960
3961 if pi_raw(ctxt) != b'<' {
3963 if (*ctxt).wellFormed != 0 {
3964 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_EMPTY);
3965 }
3966 } else {
3967 pi_parse_element(ctxt);
3968 pi_parse_misc(ctxt);
3969 if !pi_stopped(ctxt) {
3971 let input = pi_input(ctxt);
3972 if !input.is_null() && (*input).cur < (*input).end {
3973 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_END);
3974 }
3975 }
3976 }
3977
3978 let c = &mut *ctxt;
3979 c.instate = XML_PARSER_EOF_STATE;
3980 if !c.sax.is_null() && c.disableSAX == 0 {
3981 SaxDispatcher::end_document(&*c.sax, c.userData);
3982 }
3983 if c.wellFormed == 0 {
3984 c.valid = 0;
3985 return -1;
3986 }
3987 0
3988 }
3989}
3990
3991unsafe fn pi_parse_ext_parsed_ent(ctxt: *mut _xmlParserCtxt) -> c_int {
3993 unsafe {
3994 if ctxt.is_null() || pi_input(ctxt).is_null() {
3995 return -1;
3996 }
3997 pi_ctxt_late_init(ctxt);
3998 if pi_raw(ctxt) == 0 {
3999 pi_fatal_err(ctxt, XML_ERR_DOCUMENT_EMPTY);
4000 }
4001 if pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
4002 pi_parse_xml_decl(ctxt);
4003 pi_skip_blanks(ctxt);
4004 } else {
4005 let c = &mut *ctxt;
4006 if !c.version.is_null() {
4007 xmlFreeImpl(c.version as *mut c_void);
4008 }
4009 c.version = crate::abi::exports_xml2::xmlStrdup(c"1.0".as_ptr() as *const xmlChar);
4010 }
4011 let c0 = &*ctxt;
4012 if !c0.sax.is_null() && c0.disableSAX == 0 {
4013 SaxDispatcher::start_document(&*c0.sax, c0.userData);
4014 }
4015 let c1 = &mut *ctxt;
4016 c1.options &= !XML_PARSE_DTDVALID;
4017 c1.validate = 0;
4018 c1.depth = 0;
4019
4020 pi_parse_content(ctxt);
4021
4022 let input = pi_input(ctxt);
4023 if !input.is_null() && (*input).cur < (*input).end {
4024 pi_fatal_err(ctxt, XML_ERR_NOT_WELL_BALANCED);
4025 }
4026 let c2 = &*ctxt;
4027 if !c2.sax.is_null() && c2.disableSAX == 0 {
4028 SaxDispatcher::end_document(&*c2.sax, c2.userData);
4029 }
4030 if (*ctxt).wellFormed == 0 {
4031 return -1;
4032 }
4033 0
4034 }
4035}
4036
4037unsafe fn pi_parse_content_node_list(
4040 ctxt: *mut _xmlParserCtxt,
4041 input: *mut _xmlParserInput,
4042 has_text_decl: c_int,
4043) -> *mut _xmlNode {
4044 unsafe {
4045 let mut root: *mut _xmlNode = ptr::null_mut();
4046 let mut list: *mut _xmlNode = ptr::null_mut();
4047 let root_name = b"#root\0";
4048 let root_name_owned = pi_strndup_bytes(root_name.as_ptr(), 5);
4053 if root_name_owned.is_null() {
4054 pi_err_memory(ctxt);
4055 return ptr::null_mut();
4056 }
4057 root = crate::xml::tree::new_node(ptr::null_mut(), root_name_owned as *const xmlChar);
4058 if root.is_null() {
4059 xmlFreeImpl(root_name_owned as *mut c_void);
4060 pi_err_memory(ctxt);
4061 return ptr::null_mut();
4062 }
4063 (*root).doc = (*ctxt).myDoc;
4069 if pi_input_push(ctxt, input) < 0 {
4070 crate::xml::tree::free_node(root);
4071 xmlFreeImpl(root_name_owned as *mut c_void);
4072 return ptr::null_mut();
4073 }
4074 pi_name_push(ctxt, root_name_owned as *const xmlChar);
4075 pi_space_push(ctxt, -1);
4076 pi_node_push(ctxt, root);
4077
4078 if has_text_decl != 0 && pi_cmp5(ctxt, b"<?xml") && pi_is_blank_ch(pi_nxt(ctxt, 5)) {
4079 pi_parse_text_decl(ctxt);
4080 }
4081
4082 pi_parse_content(ctxt);
4083
4084 let cur = pi_input(ctxt);
4085 if !cur.is_null() && (*cur).cur < (*cur).end {
4086 pi_fatal_err(ctxt, XML_ERR_NOT_WELL_BALANCED);
4087 }
4088
4089 if (*ctxt).wellFormed != 0 {
4090 list = (*root).children;
4092 (*root).children = ptr::null_mut();
4093 (*root).last = ptr::null_mut();
4094 let mut n = list;
4095 while !n.is_null() {
4096 (*n).parent = ptr::null_mut();
4097 n = (*n).next;
4098 }
4099 }
4100
4101 if pi_input_pop(ctxt) == input {
4102 crate::xml::parser::helpers::free_parser_input(input);
4106 }
4107 pi_node_pop(ctxt);
4108 pi_name_pop(ctxt);
4109 pi_space_pop(ctxt);
4110 crate::xml::tree::free_node(root);
4111 list
4112 }
4113}
4114
4115#[no_mangle]
4125pub unsafe extern "C" fn xmlNamespaceParseNCName(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4126 if ctxt.is_null() || pi_input(ctxt).is_null() {
4127 return ptr::null();
4128 }
4129 unsafe {
4130 let start = pi_cur_ptr(ctxt);
4131 let (c, l) = pi_current_char(ctxt);
4132 if (c != b'_' as c_int && !pi_is_letter_ch(c as u8)) || c == b':' as c_int {
4133 return ptr::null();
4134 }
4135 pi_nextl(ctxt, l);
4136 loop {
4137 let (c2, l2) = pi_current_char(ctxt);
4138 if !pi_is_name_char(c2) || c2 == b':' as c_int {
4139 break;
4140 }
4141 pi_nextl(ctxt, l2);
4142 }
4143 let len = pi_cur_ptr(ctxt).offset_from(start) as usize;
4144 if len == 0 {
4145 return ptr::null();
4146 }
4147 pi_strndup_bytes(start, len)
4148 }
4149}
4150
4151#[no_mangle]
4157pub unsafe extern "C" fn xmlNamespaceParseQName(
4158 ctxt: *mut _xmlParserCtxt,
4159 prefix: *mut *mut xmlChar,
4160) -> *const xmlChar {
4161 if ctxt.is_null() || pi_input(ctxt).is_null() {
4162 return ptr::null();
4163 }
4164 unsafe {
4165 if !prefix.is_null() {
4166 *prefix = ptr::null_mut();
4167 }
4168 let start = pi_cur_ptr(ctxt);
4169 let (c, l) = pi_current_char(ctxt);
4170 if (c != b'_' as c_int && !pi_is_letter_ch(c as u8)) || c == b':' as c_int {
4171 return ptr::null();
4172 }
4173 pi_nextl(ctxt, l);
4174 loop {
4175 let (c2, l2) = pi_current_char(ctxt);
4176 if !pi_is_name_char(c2) || c2 == b':' as c_int {
4177 break;
4178 }
4179 pi_nextl(ctxt, l2);
4180 }
4181 if pi_raw(ctxt) == b':' {
4182 pi_next1(ctxt);
4183 if !prefix.is_null() {
4184 let plen = pi_cur_ptr(ctxt).offset_from(start) as usize - 1;
4185 *prefix = pi_strndup_bytes(start, plen);
4186 }
4187 let lstart = pi_cur_ptr(ctxt);
4188 let (c2, l2) = pi_current_char(ctxt);
4189 if (c2 != b'_' as c_int && !pi_is_letter_ch(c2 as u8)) || c2 == b':' as c_int {
4190 return ptr::null();
4191 }
4192 pi_nextl(ctxt, l2);
4193 loop {
4194 let (c3, l3) = pi_current_char(ctxt);
4195 if !pi_is_name_char(c3) || c3 == b':' as c_int {
4196 break;
4197 }
4198 pi_nextl(ctxt, l3);
4199 }
4200 let llen = pi_cur_ptr(ctxt).offset_from(lstart) as usize;
4201 return pi_strndup_bytes(lstart, llen);
4202 }
4203 let len = pi_cur_ptr(ctxt).offset_from(start) as usize;
4204 if len == 0 {
4205 return ptr::null();
4206 }
4207 pi_strndup_bytes(start, len)
4208 }
4209}
4210
4211#[no_mangle]
4217pub unsafe extern "C" fn xmlNamespaceParseNSDef(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4218 if ctxt.is_null() || pi_input(ctxt).is_null() {
4219 return ptr::null();
4220 }
4221 unsafe {
4222 let start = pi_cur_ptr(ctxt);
4223 if !pi_cmp5(ctxt, b"xmlns") {
4224 return ptr::null();
4225 }
4226 pi_skip(ctxt, 5);
4227 if pi_raw(ctxt) == b':' {
4228 pi_next1(ctxt);
4229 let (c, l) = pi_current_char(ctxt);
4230 if (c != b'_' as c_int && !pi_is_letter_ch(c as u8)) || c == b':' as c_int {
4231 return ptr::null();
4232 }
4233 pi_nextl(ctxt, l);
4234 loop {
4235 let (c2, l2) = pi_current_char(ctxt);
4236 if !pi_is_name_char(c2) || c2 == b':' as c_int {
4237 break;
4238 }
4239 pi_nextl(ctxt, l2);
4240 }
4241 }
4242 let len = pi_cur_ptr(ctxt).offset_from(start) as usize;
4243 pi_strndup_bytes(start, len)
4244 }
4245}
4246
4247#[no_mangle]
4255pub unsafe extern "C" fn xmlParseNamespace(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4256 if ctxt.is_null() || pi_input(ctxt).is_null() {
4257 return ptr::null();
4258 }
4259 unsafe {
4260 let name = xmlNamespaceParseNSDef(ctxt);
4261 if name.is_null() {
4262 return ptr::null();
4263 }
4264 pi_skip_blanks(ctxt);
4265 if pi_raw(ctxt) == b'=' {
4266 pi_next1(ctxt);
4267 pi_skip_blanks(ctxt);
4268 let value = pi_parse_att_value(ctxt);
4269 if value.is_null() {
4270 pi_fatal_err(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE);
4271 return name;
4272 }
4273 xmlFreeImpl(value as *mut c_void);
4274 }
4275 name
4276 }
4277}
4278
4279#[no_mangle]
4285pub unsafe extern "C" fn xmlParseQuotedString(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4286 pi_parse_quoted_string(ctxt)
4287}
4288
4289#[no_mangle]
4295pub unsafe extern "C" fn xmlParseName(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4296 pi_parse_name(ctxt)
4297}
4298
4299#[no_mangle]
4305pub unsafe extern "C" fn xmlParseNmtoken(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4306 pi_parse_nmtoken(ctxt)
4307}
4308
4309#[no_mangle]
4315pub unsafe extern "C" fn xmlParseCharRef(ctxt: *mut _xmlParserCtxt) -> c_int {
4316 pi_parse_char_ref(ctxt)
4317}
4318
4319#[no_mangle]
4325pub unsafe extern "C" fn xmlParseEntityRef(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEntity {
4326 pi_parse_entity_ref(ctxt)
4327}
4328
4329#[no_mangle]
4335pub unsafe extern "C" fn xmlParseEntityValue(
4336 ctxt: *mut _xmlParserCtxt,
4337 orig: *mut *mut xmlChar,
4338) -> *mut xmlChar {
4339 pi_parse_entity_value(ctxt, orig)
4340}
4341
4342#[no_mangle]
4348pub unsafe extern "C" fn xmlParseAttValue(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4349 pi_parse_att_value(ctxt)
4350}
4351
4352#[no_mangle]
4358pub unsafe extern "C" fn xmlParseSystemLiteral(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4359 pi_parse_system_literal(ctxt)
4360}
4361
4362#[no_mangle]
4368pub unsafe extern "C" fn xmlParsePubidLiteral(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4369 pi_parse_pubid_literal(ctxt)
4370}
4371
4372#[no_mangle]
4378pub unsafe extern "C" fn xmlParseExternalID(
4379 ctxt: *mut _xmlParserCtxt,
4380 public_id: *mut *mut xmlChar,
4381 strict: c_int,
4382) -> *mut xmlChar {
4383 if ctxt.is_null() || public_id.is_null() {
4384 return ptr::null_mut();
4385 }
4386 pi_parse_external_id(ctxt, public_id, strict)
4387}
4388
4389#[no_mangle]
4395pub unsafe extern "C" fn xmlParsePITarget(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4396 pi_parse_pi_target(ctxt)
4397}
4398
4399#[no_mangle]
4405pub unsafe extern "C" fn xmlParsePI(ctxt: *mut _xmlParserCtxt) {
4406 pi_parse_pi(ctxt)
4407}
4408
4409#[no_mangle]
4415pub unsafe extern "C" fn xmlParseComment(ctxt: *mut _xmlParserCtxt) {
4416 pi_parse_comment(ctxt)
4417}
4418
4419#[no_mangle]
4425pub unsafe extern "C" fn xmlParseCharData(ctxt: *mut _xmlParserCtxt, cdata: c_int) {
4426 pi_parse_char_data(ctxt, cdata)
4427}
4428
4429#[no_mangle]
4435pub unsafe extern "C" fn xmlParseCDSect(ctxt: *mut _xmlParserCtxt) {
4436 pi_parse_cd_sect(ctxt)
4437}
4438
4439#[no_mangle]
4445pub unsafe extern "C" fn xmlParseReference(ctxt: *mut _xmlParserCtxt) {
4446 pi_parse_reference(ctxt)
4447}
4448
4449#[no_mangle]
4455pub unsafe extern "C" fn xmlParserHandleReference(ctxt: *mut _xmlParserCtxt) {
4456 pi_parse_reference(ctxt)
4457}
4458
4459#[no_mangle]
4465pub unsafe extern "C" fn xmlParsePEReference(ctxt: *mut _xmlParserCtxt) {
4466 pi_parse_pe_reference(ctxt)
4467}
4468
4469#[no_mangle]
4475pub unsafe extern "C" fn xmlParserHandlePEReference(ctxt: *mut _xmlParserCtxt) {
4476 pi_parse_pe_reference(ctxt)
4477}
4478
4479#[no_mangle]
4485pub unsafe extern "C" fn xmlParseNotationDecl(ctxt: *mut _xmlParserCtxt) {
4486 pi_parse_notation_decl(ctxt)
4487}
4488
4489#[no_mangle]
4495pub unsafe extern "C" fn xmlParseEntityDecl(ctxt: *mut _xmlParserCtxt) {
4496 pi_parse_entity_decl(ctxt)
4497}
4498
4499#[no_mangle]
4505pub unsafe extern "C" fn xmlParseDefaultDecl(
4506 ctxt: *mut _xmlParserCtxt,
4507 value: *mut *mut xmlChar,
4508) -> c_int {
4509 if ctxt.is_null() || value.is_null() {
4510 return 0;
4511 }
4512 pi_parse_default_decl(ctxt, value)
4513}
4514
4515#[no_mangle]
4521pub unsafe extern "C" fn xmlParseAttributeType(
4522 ctxt: *mut _xmlParserCtxt,
4523 tree: *mut *mut _xmlEnumeration,
4524) -> c_int {
4525 if ctxt.is_null() || tree.is_null() {
4526 return 0;
4527 }
4528 pi_parse_attribute_type(ctxt, tree)
4529}
4530
4531#[no_mangle]
4537pub unsafe extern "C" fn xmlParseNotationType(ctxt: *mut _xmlParserCtxt) -> *mut _xmlEnumeration {
4538 pi_parse_notation_type(ctxt)
4539}
4540
4541#[no_mangle]
4547pub unsafe extern "C" fn xmlParseEnumerationType(
4548 ctxt: *mut _xmlParserCtxt,
4549) -> *mut _xmlEnumeration {
4550 pi_parse_enumeration_type(ctxt)
4551}
4552
4553#[no_mangle]
4559pub unsafe extern "C" fn xmlParseEnumeratedType(
4560 ctxt: *mut _xmlParserCtxt,
4561 tree: *mut *mut _xmlEnumeration,
4562) -> c_int {
4563 if ctxt.is_null() || tree.is_null() {
4564 return 0;
4565 }
4566 pi_parse_enumerated_type(ctxt, tree)
4567}
4568
4569#[no_mangle]
4575pub unsafe extern "C" fn xmlParseAttributeListDecl(ctxt: *mut _xmlParserCtxt) {
4576 pi_parse_attribute_list_decl(ctxt)
4577}
4578
4579#[no_mangle]
4585pub unsafe extern "C" fn xmlParseElementMixedContentDecl(
4586 ctxt: *mut _xmlParserCtxt,
4587 inputchk: c_int,
4588) -> *mut _xmlElementContent {
4589 pi_parse_element_mixed_content_decl(ctxt, inputchk)
4590}
4591
4592#[no_mangle]
4598pub unsafe extern "C" fn xmlParseElementChildrenContentDecl(
4599 ctxt: *mut _xmlParserCtxt,
4600 inputchk: c_int,
4601) -> *mut _xmlElementContent {
4602 pi_parse_element_children_content_decl_priv(ctxt, inputchk, 1)
4603}
4604
4605#[no_mangle]
4612pub unsafe extern "C" fn xmlParseElementContentDecl(
4613 ctxt: *mut _xmlParserCtxt,
4614 name: *const xmlChar,
4615 result: *mut *mut _xmlElementContent,
4616) -> c_int {
4617 if ctxt.is_null() || result.is_null() {
4618 return -1;
4619 }
4620 pi_parse_element_content_decl(ctxt, name, result)
4621}
4622
4623#[no_mangle]
4629pub unsafe extern "C" fn xmlParseElementDecl(ctxt: *mut _xmlParserCtxt) -> c_int {
4630 pi_parse_element_decl(ctxt)
4631}
4632
4633#[no_mangle]
4639pub unsafe extern "C" fn xmlParseMarkupDecl(ctxt: *mut _xmlParserCtxt) {
4640 pi_parse_markup_decl(ctxt)
4641}
4642
4643#[no_mangle]
4649pub unsafe extern "C" fn xmlParseVersionNum(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4650 pi_parse_version_num(ctxt)
4651}
4652
4653#[no_mangle]
4659pub unsafe extern "C" fn xmlParseVersionInfo(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4660 pi_parse_version_info(ctxt)
4661}
4662
4663#[no_mangle]
4669pub unsafe extern "C" fn xmlParseEncName(ctxt: *mut _xmlParserCtxt) -> *mut xmlChar {
4670 pi_parse_enc_name(ctxt)
4671}
4672
4673#[no_mangle]
4679pub unsafe extern "C" fn xmlParseEncodingDecl(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4680 pi_parse_encoding_decl(ctxt)
4681}
4682
4683#[no_mangle]
4689pub unsafe extern "C" fn xmlParseSDDecl(ctxt: *mut _xmlParserCtxt) -> c_int {
4690 pi_parse_sd_decl(ctxt)
4691}
4692
4693#[no_mangle]
4699pub unsafe extern "C" fn xmlParseXMLDecl(ctxt: *mut _xmlParserCtxt) {
4700 pi_parse_xml_decl(ctxt)
4701}
4702
4703#[no_mangle]
4709pub unsafe extern "C" fn xmlParseTextDecl(ctxt: *mut _xmlParserCtxt) {
4710 pi_parse_text_decl(ctxt)
4711}
4712
4713#[no_mangle]
4720pub unsafe extern "C" fn xmlParseExternalSubset(
4721 ctxt: *mut _xmlParserCtxt,
4722 public_id: *const xmlChar,
4723 system_id: *const xmlChar,
4724) {
4725 pi_parse_external_subset(ctxt, public_id, system_id)
4726}
4727
4728#[no_mangle]
4734pub unsafe extern "C" fn xmlParseDocTypeDecl(ctxt: *mut _xmlParserCtxt) {
4735 pi_parse_doc_type_decl(ctxt)
4736}
4737
4738#[no_mangle]
4744pub unsafe extern "C" fn xmlParseAttribute(
4745 ctxt: *mut _xmlParserCtxt,
4746 value: *mut *mut xmlChar,
4747) -> *const xmlChar {
4748 if ctxt.is_null() || value.is_null() {
4749 return ptr::null();
4750 }
4751 pi_parse_attribute(ctxt, value)
4752}
4753
4754#[no_mangle]
4760pub unsafe extern "C" fn xmlParseStartTag(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
4761 pi_parse_start_tag(ctxt)
4762}
4763
4764#[no_mangle]
4770pub unsafe extern "C" fn xmlParseEndTag(ctxt: *mut _xmlParserCtxt) {
4771 pi_parse_end_tag(ctxt)
4772}
4773
4774#[no_mangle]
4780pub unsafe extern "C" fn xmlParseElement(ctxt: *mut _xmlParserCtxt) {
4781 pi_parse_element(ctxt)
4782}
4783
4784#[no_mangle]
4790pub unsafe extern "C" fn xmlParseContent(ctxt: *mut _xmlParserCtxt) {
4791 pi_parse_content(ctxt)
4792}
4793
4794#[no_mangle]
4800pub unsafe extern "C" fn xmlParseMisc(ctxt: *mut _xmlParserCtxt) {
4801 pi_parse_misc(ctxt)
4802}
4803
4804#[no_mangle]
4815pub unsafe extern "C" fn xmlParseCtxtExternalEntity(
4816 ctxt: *mut _xmlParserCtxt,
4817 url: *const xmlChar,
4818 _id: *const xmlChar,
4819 list_out: *mut *mut _xmlNode,
4820) -> c_int {
4821 unsafe {
4822 if !list_out.is_null() {
4823 *list_out = ptr::null_mut();
4824 }
4825 if ctxt.is_null() {
4826 return XML_ERR_ARGUMENT;
4827 }
4828 if url.is_null() {
4829 pi_fatal_err(ctxt, XML_ERR_INTERNAL_ERROR);
4830 return (*ctxt).errNo;
4831 }
4832 let url_cstr = url as *const c_char;
4837 let input_buf = match crate::abi::exports_parser::open_filename_routed(url_cstr) {
4838 crate::abi::exports_parser::RoutedFileOpen::Loaded(b) => Ok(b),
4839 crate::abi::exports_parser::RoutedFileOpen::Failed => Err(()),
4840 crate::abi::exports_parser::RoutedFileOpen::Builtin => input_from_file(url_cstr),
4841 };
4842 let input_buf = match input_buf {
4843 Ok(b) => b,
4844 Err(_) => {
4845 pi_fatal_err(ctxt, XML_ERR_INTERNAL_ERROR);
4846 return (*ctxt).errNo;
4847 }
4848 };
4849 let input = {
4850 let boxed = Box::into_raw(Box::new(input_buf));
4853 let pi = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
4854 if pi.is_null() {
4855 let _ = Box::from_raw(boxed);
4856 pi_err_memory(ctxt);
4857 return (*ctxt).errNo;
4858 }
4859 (*boxed).populate_parser_input_without_filename(&mut *pi);
4860 if let Some(fname) = (*boxed).filename() {
4865 (*pi).filename = crate::xml::string::xml_strndup(
4866 fname.as_ptr() as *const crate::abi::types::xmlChar,
4867 fname.len(),
4868 ) as *const c_char;
4869 }
4870 (*pi).buf = ptr::null_mut();
4871 (*pi).directory = ptr::null();
4872 (*pi).free = None;
4873 (*pi).encoding = ptr::null();
4874 (*pi).version = ptr::null();
4875 (*pi).flags = 0;
4876 (*pi).id = 0;
4877 (*pi).parentConsumed = 0;
4878 (*pi).entity = ptr::null_mut();
4879 crate::xml::parser::helpers::stash_input_buffer(ctxt, boxed);
4882 pi
4883 };
4884
4885 pi_ctxt_late_init(ctxt);
4886 let list = pi_parse_content_node_list(ctxt, input, 1);
4887 if !list_out.is_null() {
4888 *list_out = list;
4889 } else if !list.is_null() {
4890 crate::xml::tree::free_node_list(list);
4891 }
4892 (*ctxt).errNo
4893 }
4894}
4895
4896#[no_mangle]
4904pub unsafe extern "C" fn xmlParseExternalEntity(
4905 doc: *mut _xmlDoc,
4906 sax: *mut _xmlSAXHandler,
4907 user_data: *mut c_void,
4908 depth: c_int,
4909 url: *const xmlChar,
4910 id: *const xmlChar,
4911 list: *mut *mut _xmlNode,
4912) -> c_int {
4913 unsafe {
4914 if !list.is_null() {
4915 *list = ptr::null_mut();
4916 }
4917 if doc.is_null() {
4918 return XML_ERR_ARGUMENT;
4919 }
4920 let ctxt = create_parser_ctxt();
4921 if ctxt.is_null() {
4922 return XML_ERR_NO_MEMORY;
4923 }
4924 if !sax.is_null() {
4926 let dst = (*ctxt).sax;
4927 if !dst.is_null() {
4928 ptr::copy_nonoverlapping(sax, dst, 1);
4930 }
4931 (*ctxt).userData = user_data;
4932 }
4933 (*ctxt).depth = depth;
4934 (*ctxt).myDoc = doc;
4935 let ret = xmlParseCtxtExternalEntity(ctxt, url, id, list);
4936 free_parser_ctxt(ctxt);
4937 ret
4938 }
4939}
4940
4941#[no_mangle]
4948pub unsafe extern "C" fn xmlParseBalancedChunkMemory(
4949 doc: *mut _xmlDoc,
4950 sax: *mut _xmlSAXHandler,
4951 user_data: *mut c_void,
4952 depth: c_int,
4953 string: *const xmlChar,
4954 lst: *mut *mut _xmlNode,
4955) -> c_int {
4956 xmlParseBalancedChunkMemoryRecover(doc, sax, user_data, depth, string, lst, 0)
4957}
4958
4959#[no_mangle]
4968pub unsafe extern "C" fn xmlParseBalancedChunkMemoryRecover(
4969 doc: *mut _xmlDoc,
4970 sax: *mut _xmlSAXHandler,
4971 user_data: *mut c_void,
4972 depth: c_int,
4973 string: *const xmlChar,
4974 list_out: *mut *mut _xmlNode,
4975 recover: c_int,
4976) -> c_int {
4977 unsafe {
4978 if !list_out.is_null() {
4979 *list_out = ptr::null_mut();
4980 }
4981 if string.is_null() {
4982 return XML_ERR_ARGUMENT;
4983 }
4984 if doc.is_null() {
4985 return XML_ERR_ARGUMENT;
4986 }
4987 let ctxt = create_parser_ctxt();
4988 if ctxt.is_null() {
4989 return XML_ERR_NO_MEMORY;
4990 }
4991 if !sax.is_null() {
4992 let dst = (*ctxt).sax;
4993 if !dst.is_null() {
4994 ptr::copy_nonoverlapping(sax, dst, 1);
4995 }
4996 (*ctxt).userData = user_data;
4997 }
4998 pi_ctxt_late_init(ctxt);
4999 (*ctxt).depth = depth;
5000 (*ctxt).myDoc = doc;
5001 if recover != 0 {
5002 (*ctxt).options |= XML_PARSE_RECOVER;
5003 (*ctxt).recovery = 1;
5004 }
5005
5006 let slen = crate::abi::exports_xml2::xmlStrlen(string) as c_int;
5007 let input_buf = input_from_memory(string as *const c_char, slen);
5008 let boxed = Box::into_raw(Box::new(input_buf));
5011 crate::xml::parser::helpers::stash_input_buffer(ctxt, boxed);
5012 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
5013 if input.is_null() {
5014 let _ = Box::from_raw(boxed);
5015 crate::xml::parser::helpers::free_stashed_input_buffer(ctxt);
5016 let ret = (*ctxt).errNo;
5017 free_parser_ctxt(ctxt);
5018 return if ret != 0 { ret } else { XML_ERR_NO_MEMORY };
5019 }
5020 (*boxed).populate_parser_input_without_filename(&mut *input);
5021 if let Some(fname) = (*boxed).filename() {
5022 (*input).filename = crate::xml::string::xml_strndup(
5023 fname.as_ptr() as *const crate::abi::types::xmlChar,
5024 fname.len(),
5025 ) as *const c_char;
5026 }
5027 (*input).buf = ptr::null_mut();
5028 (*input).directory = ptr::null();
5029 (*input).free = None;
5030 (*input).encoding = ptr::null();
5031 (*input).version = ptr::null();
5032 (*input).flags = 0;
5033 (*input).id = 0;
5034 (*input).parentConsumed = 0;
5035 (*input).entity = ptr::null_mut();
5036
5037 let list = pi_parse_content_node_list(ctxt, input, 0);
5038 if !list_out.is_null() {
5039 *list_out = list;
5040 } else if !list.is_null() {
5041 crate::xml::tree::free_node_list(list);
5042 }
5043 let ret = if (*ctxt).wellFormed == 0 {
5044 (*ctxt).errNo
5045 } else {
5046 XML_ERR_OK
5047 };
5048 free_parser_ctxt(ctxt);
5049 ret
5050 }
5051}
5052
5053#[no_mangle]
5060pub unsafe extern "C" fn xmlParseInNodeContext(
5061 node: *mut _xmlNode,
5062 data: *const c_char,
5063 datalen: c_int,
5064 options: c_int,
5065 list_out: *mut *mut _xmlNode,
5066) -> c_int {
5067 unsafe {
5068 if list_out.is_null() {
5069 return XML_ERR_INTERNAL_ERROR;
5070 }
5071 *list_out = ptr::null_mut();
5072 if node.is_null() || data.is_null() || datalen < 0 {
5073 return XML_ERR_INTERNAL_ERROR;
5074 }
5075 let doc = (*node).doc;
5076 if doc.is_null() {
5077 return XML_ERR_INTERNAL_ERROR;
5078 }
5079 let ctxt = create_parser_ctxt();
5080 if ctxt.is_null() {
5081 return XML_ERR_NO_MEMORY;
5082 }
5083 (*ctxt).options = options;
5084
5085 let input_buf = input_from_memory(data, datalen);
5086 let boxed = Box::into_raw(Box::new(input_buf));
5087 crate::xml::parser::helpers::stash_input_buffer(ctxt, boxed);
5088 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
5089 if input.is_null() {
5090 let _ = Box::from_raw(boxed);
5091 crate::xml::parser::helpers::free_stashed_input_buffer(ctxt);
5092 free_parser_ctxt(ctxt);
5093 return XML_ERR_NO_MEMORY;
5094 }
5095 (*boxed).populate_parser_input_without_filename(&mut *input);
5096 if let Some(fname) = (*boxed).filename() {
5097 (*input).filename = crate::xml::string::xml_strndup(
5098 fname.as_ptr() as *const crate::abi::types::xmlChar,
5099 fname.len(),
5100 ) as *const c_char;
5101 }
5102 (*input).buf = ptr::null_mut();
5103 (*input).directory = ptr::null();
5104 (*input).free = None;
5105 (*input).encoding = ptr::null();
5106 (*input).version = ptr::null();
5107 (*input).flags = 0;
5108 (*input).id = 0;
5109 (*input).parentConsumed = 0;
5110 (*input).entity = ptr::null_mut();
5111
5112 pi_ctxt_late_init(ctxt);
5113 (*ctxt).myDoc = doc;
5114
5115 let mut ns_cur = (*node).nsDef;
5118 while !ns_cur.is_null() {
5119 let nsp = ns_cur;
5120 ns_cur = (*ns_cur).next;
5121 if !(*nsp).prefix.is_null() {
5124 }
5126 }
5127
5128 let list = pi_parse_content_node_list(ctxt, input, 0);
5129 if list.is_null() {
5130 let ret = (*ctxt).errNo;
5131 if ret == XML_ERR_ARGUMENT {
5132 free_parser_ctxt(ctxt);
5133 return XML_ERR_INTERNAL_ERROR;
5134 }
5135 free_parser_ctxt(ctxt);
5136 return if ret != 0 {
5137 ret
5138 } else {
5139 XML_ERR_INTERNAL_ERROR
5140 };
5141 }
5142 *list_out = list;
5143 free_parser_ctxt(ctxt);
5144 XML_ERR_OK
5145 }
5146}
5147
5148#[no_mangle]
5154pub unsafe extern "C" fn xmlParseDTD(
5155 public_id: *const xmlChar,
5156 system_id: *const xmlChar,
5157) -> *mut _xmlDtd {
5158 unsafe {
5159 if public_id.is_null() && system_id.is_null() {
5160 return ptr::null_mut();
5161 }
5162 if system_id.is_null() {
5163 return ptr::null_mut();
5164 }
5165 let ctxt = create_parser_ctxt();
5166 if ctxt.is_null() {
5167 return ptr::null_mut();
5168 }
5169 pi_ctxt_late_init(ctxt);
5170 (*ctxt).inSubset = 2;
5171 (*ctxt).hasExternalSubset = 1;
5172
5173 let mut ret: *mut _xmlDtd = ptr::null_mut();
5174 let input_buf =
5175 match crate::abi::exports_parser::open_filename_routed(system_id as *const c_char) {
5176 crate::abi::exports_parser::RoutedFileOpen::Loaded(b) => Ok(b),
5177 crate::abi::exports_parser::RoutedFileOpen::Failed => Err(()),
5178 crate::abi::exports_parser::RoutedFileOpen::Builtin => {
5179 input_from_file(system_id as *const c_char)
5180 }
5181 };
5182 if input_buf.is_err() {
5183 crate::abi::exports_parser::emit_io_warning(
5188 ctxt,
5189 crate::abi::exports_parser::io_load_failure_message(system_id as *const c_char),
5190 );
5191 }
5192 if let Ok(input_buf) = input_buf {
5193 let boxed = Box::into_raw(Box::new(input_buf));
5194 crate::xml::parser::helpers::stash_input_buffer(ctxt, boxed);
5195 let input = xmlMallocZero(size_of::<_xmlParserInput>()) as *mut _xmlParserInput;
5196 if !input.is_null() {
5197 (*boxed).populate_parser_input_without_filename(&mut *input);
5198 if let Some(fname) = (*boxed).filename() {
5199 (*input).filename = crate::xml::string::xml_strndup(
5200 fname.as_ptr() as *const crate::abi::types::xmlChar,
5201 fname.len(),
5202 ) as *const c_char;
5203 }
5204 (*input).buf = ptr::null_mut();
5205 (*input).directory = ptr::null();
5206 (*input).free = None;
5207 (*input).encoding = ptr::null();
5208 (*input).version = ptr::null();
5209 (*input).flags = 0;
5210 (*input).id = 0;
5211 (*input).parentConsumed = 0;
5212 (*input).entity = ptr::null_mut();
5213 (*ctxt).input = input;
5215 (*ctxt).inputNr = 1;
5216 let tab = xmlMallocZero(4 * size_of::<*mut _xmlParserInput>())
5217 as *mut *mut _xmlParserInput;
5218 if !tab.is_null() {
5219 *tab = input;
5220 (*ctxt).inputTab = tab;
5221 (*ctxt).inputMax = 4;
5222 }
5223 pi_parse_external_subset(ctxt, public_id, system_id);
5224 }
5225 }
5226
5227 if (*ctxt).wellFormed != 0 && !(*ctxt).myDoc.is_null() {
5228 let doc = (*ctxt).myDoc;
5229 if !(*doc).intSubset.is_null() {
5230 ret = (*doc).intSubset;
5231 } else if !(*doc).extSubset.is_null() {
5232 ret = (*doc).extSubset;
5233 }
5234 }
5235 free_parser_ctxt(ctxt);
5236 ret
5237 }
5238}
5239
5240#[no_mangle]
5246pub unsafe extern "C" fn xmlParseEntity(filename: *const c_char) -> *mut _xmlDoc {
5247 unsafe {
5248 if filename.is_null() {
5249 return ptr::null_mut();
5250 }
5251 let ctxt = create_parser_ctxt();
5252 if ctxt.is_null() {
5253 return ptr::null_mut();
5254 }
5255 let input_buf = match crate::abi::exports_parser::open_filename_routed(filename) {
5256 crate::abi::exports_parser::RoutedFileOpen::Loaded(b) => b,
5257 crate::abi::exports_parser::RoutedFileOpen::Failed => {
5258 crate::abi::exports_parser::emit_io_warning(
5259 ctxt,
5260 crate::abi::exports_parser::io_load_failure_message(filename),
5261 );
5262 free_parser_ctxt(ctxt);
5263 return ptr::null_mut();
5264 }
5265 crate::abi::exports_parser::RoutedFileOpen::Builtin => {
5266 match input_from_file(filename) {
5267 Ok(b) => b,
5268 Err(_) => {
5269 free_parser_ctxt(ctxt);
5270 return ptr::null_mut();
5271 }
5272 }
5273 }
5274 };
5275 setup_parser_input(ctxt, input_buf);
5276 xmlParseExtParsedEnt(ctxt);
5277 let ret = if (*ctxt).wellFormed != 0 {
5278 (*ctxt).myDoc
5279 } else {
5280 let doc = (*ctxt).myDoc;
5281 if !doc.is_null() {
5282 crate::xml::tree::free_doc(doc);
5283 (*ctxt).myDoc = ptr::null_mut();
5284 }
5285 ptr::null_mut()
5286 };
5287 (*ctxt).myDoc = ptr::null_mut();
5289 free_parser_ctxt(ctxt);
5290 ret
5291 }
5292}
5293
5294#[no_mangle]
5300pub unsafe extern "C" fn xmlParseExtParsedEnt(ctxt: *mut _xmlParserCtxt) -> c_int {
5301 pi_parse_ext_parsed_ent(ctxt)
5302}
5303
5304#[repr(C)]
5326struct PiInputMem {
5327 data: *mut u8,
5328 len: usize,
5329 cap: usize,
5330 owned: bool,
5331}
5332
5333unsafe fn pi_mem_create() -> *mut PiInputMem {
5334 unsafe { xmlMallocZero(size_of::<PiInputMem>()) as *mut PiInputMem }
5335}
5336
5337unsafe fn pi_mem_free(m: *mut PiInputMem) {
5338 unsafe {
5339 if m.is_null() {
5340 return;
5341 }
5342 if !(*m).data.is_null() && (*m).owned {
5343 xmlFreeImpl((*m).data as *mut c_void);
5344 }
5345 xmlFreeImpl(m as *mut c_void);
5346 }
5347}
5348
5349unsafe fn pi_mem_grow(m: *mut PiInputMem, extra: usize) -> bool {
5350 unsafe {
5351 if m.is_null() {
5352 return false;
5353 }
5354 if (*m).len + extra <= (*m).cap {
5355 return true;
5356 }
5357 let mut new_cap = if (*m).cap == 0 { 256 } else { (*m).cap };
5358 while new_cap < (*m).len + extra {
5359 new_cap *= 2;
5360 }
5361 if !(*m).owned {
5362 let data = xmlMallocImpl(new_cap) as *mut u8;
5364 if data.is_null() {
5365 return false;
5366 }
5367 if (*m).len > 0 && !(*m).data.is_null() {
5368 ptr::copy_nonoverlapping((*m).data, data, (*m).len);
5369 }
5370 (*m).data = data;
5371 (*m).owned = true;
5372 (*m).cap = new_cap;
5373 return true;
5374 }
5375 let data = xmlReallocImpl((*m).data as *mut c_void, new_cap) as *mut u8;
5376 if data.is_null() {
5377 return false;
5378 }
5379 (*m).data = data;
5380 (*m).cap = new_cap;
5381 true
5382 }
5383}
5384
5385unsafe extern "C" fn pi_fd_read(context: *mut c_void, buffer: *mut c_char, len: c_int) -> c_int {
5387 unsafe {
5388 if context.is_null() || buffer.is_null() || len <= 0 {
5389 return -1;
5390 }
5391 let fd = *(context as *const c_int);
5392 libc::read(fd, buffer as *mut c_void, len as usize) as c_int
5393 }
5394}
5395
5396unsafe extern "C" fn pi_fd_close(context: *mut c_void) -> c_int {
5398 unsafe {
5399 if context.is_null() {
5400 return -1;
5401 }
5402 let _ = Box::from_raw(context as *mut c_int);
5403 0
5404 }
5405}
5406
5407unsafe extern "C" fn pi_file_read(context: *mut c_void, buffer: *mut c_char, len: c_int) -> c_int {
5409 unsafe {
5410 if context.is_null() || buffer.is_null() || len <= 0 {
5411 return -1;
5412 }
5413 libc::fread(
5414 buffer as *mut c_void,
5415 1,
5416 len as usize,
5417 context as *mut libc::FILE,
5418 ) as c_int
5419 }
5420}
5421
5422#[no_mangle]
5428pub unsafe extern "C" fn xmlParserInputBufferCreateFd(
5429 fd: c_int,
5430 _enc: c_int,
5431) -> *mut _xmlParserInputBuffer {
5432 unsafe {
5433 if fd < 0 {
5434 return ptr::null_mut();
5435 }
5436 let buf = crate::xml::parser::helpers::alloc_parser_input_buffer();
5437 if buf.is_null() {
5438 return ptr::null_mut();
5439 }
5440 let fd_box = Box::into_raw(Box::new(fd));
5441 (*buf).context = fd_box as *mut c_void;
5442 (*buf).readcallback = Some(pi_fd_read);
5443 (*buf).closecallback = Some(pi_fd_close);
5444 (*buf).compressed = -1;
5445 (*buf).buffer = pi_mem_create() as *mut c_void;
5446 buf
5447 }
5448}
5449
5450#[no_mangle]
5456pub unsafe extern "C" fn xmlParserInputBufferCreateFile(
5457 file: *mut c_void,
5458 _enc: c_int,
5459) -> *mut _xmlParserInputBuffer {
5460 unsafe {
5461 if file.is_null() {
5462 return ptr::null_mut();
5463 }
5464 let buf = crate::xml::parser::helpers::alloc_parser_input_buffer();
5465 if buf.is_null() {
5466 return ptr::null_mut();
5467 }
5468 (*buf).context = file;
5469 (*buf).readcallback = Some(pi_file_read);
5470 (*buf).closecallback = None;
5471 (*buf).compressed = -1;
5472 (*buf).buffer = pi_mem_create() as *mut c_void;
5473 buf
5474 }
5475}
5476
5477#[no_mangle]
5484pub unsafe extern "C" fn xmlParserInputBufferCreateStatic(
5485 mem: *const c_char,
5486 size: c_int,
5487 _enc: c_int,
5488) -> *mut _xmlParserInputBuffer {
5489 unsafe {
5490 if mem.is_null() || size < 0 {
5491 return ptr::null_mut();
5492 }
5493 let buf = crate::xml::parser::helpers::alloc_parser_input_buffer();
5494 if buf.is_null() {
5495 return ptr::null_mut();
5496 }
5497 let m = pi_mem_create();
5498 if m.is_null() {
5499 crate::xml::parser::helpers::free_parser_input_buffer(buf);
5500 return ptr::null_mut();
5501 }
5502 (*m).data = mem as *mut u8;
5503 (*m).len = size as usize;
5504 (*m).cap = size as usize;
5505 (*m).owned = false;
5506 (*buf).buffer = m as *mut c_void;
5507 (*buf).compressed = -1;
5508 buf
5509 }
5510}
5511
5512unsafe extern "C" fn pi_default_input_buffer_create_filename(
5515 _uri: *const c_char,
5516 _enc: c_int,
5517) -> *mut _xmlParserInputBuffer {
5518 unsafe { crate::xml::parser::helpers::alloc_parser_input_buffer() }
5519}
5520
5521#[no_mangle]
5528#[allow(
5533 renamed_and_removed_lints,
5534 clippy::fn_address_comparisons,
5535 unpredictable_function_pointer_comparisons
5536)]
5537pub unsafe extern "C" fn xmlParserInputBufferCreateFilenameDefault(
5538 func: Option<unsafe extern "C" fn(*const c_char, c_int) -> *mut _xmlParserInputBuffer>,
5539) -> Option<unsafe extern "C" fn(*const c_char, c_int) -> *mut _xmlParserInputBuffer> {
5540 let default_fn: unsafe extern "C" fn(*const c_char, c_int) -> *mut _xmlParserInputBuffer =
5541 pi_default_input_buffer_create_filename;
5542 let old = crate::xml::globals::get_parser_input_buffer_create_filename_value();
5543 crate::xml::globals::set_parser_input_buffer_create_filename_value(
5544 if func == Some(default_fn) { None } else { func },
5545 );
5546 old.or(Some(default_fn))
5547}
5548
5549unsafe fn pi_ctxt_is_catastrophic(ctxt: *mut _xmlParserCtxt) -> c_int {
5561 if ctxt.is_null() {
5562 return 1;
5563 }
5564 unsafe {
5565 let e = (*ctxt).errNo;
5566 if e == crate::abi::types::XML_ERR_NO_MEMORY
5567 || e == crate::abi::types::XML_ERR_INTERNAL_ERROR
5568 || e == crate::abi::types::XML_ERR_RESOURCE_LIMIT
5569 {
5570 1
5571 } else {
5572 0
5573 }
5574 }
5575}
5576
5577#[no_mangle]
5579pub unsafe extern "C" fn xmlCtxtGetVersion(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
5580 if ctxt.is_null() {
5581 return ptr::null();
5582 }
5583 unsafe { (*ctxt).version as *const xmlChar }
5584}
5585
5586#[no_mangle]
5588pub unsafe extern "C" fn xmlCtxtGetStandalone(ctxt: *mut _xmlParserCtxt) -> c_int {
5589 if ctxt.is_null() {
5590 return -1;
5591 }
5592 unsafe { (*ctxt).standalone }
5593}
5594
5595#[no_mangle]
5597pub unsafe extern "C" fn xmlCtxtGetOptions(ctxt: *mut _xmlParserCtxt) -> c_int {
5598 if ctxt.is_null() {
5599 return 0;
5600 }
5601 unsafe { (*ctxt).options }
5602}
5603
5604#[no_mangle]
5606pub unsafe extern "C" fn xmlCtxtGetPrivate(ctxt: *mut _xmlParserCtxt) -> *mut c_void {
5607 if ctxt.is_null() {
5608 return ptr::null_mut();
5609 }
5610 unsafe { (*ctxt)._private }
5611}
5612
5613#[no_mangle]
5615pub unsafe extern "C" fn xmlCtxtSetPrivate(ctxt: *mut _xmlParserCtxt, priv_: *mut c_void) {
5616 if ctxt.is_null() {
5617 return;
5618 }
5619 unsafe { (*ctxt)._private = priv_ };
5620}
5621
5622#[no_mangle]
5624pub unsafe extern "C" fn xmlCtxtGetCatalogs(ctxt: *mut _xmlParserCtxt) -> *mut c_void {
5625 if ctxt.is_null() {
5626 return ptr::null_mut();
5627 }
5628 unsafe { (*ctxt).catalogs }
5629}
5630
5631#[no_mangle]
5633pub unsafe extern "C" fn xmlCtxtSetCatalogs(ctxt: *mut _xmlParserCtxt, catalogs: *mut c_void) {
5634 if ctxt.is_null() {
5635 return;
5636 }
5637 unsafe { (*ctxt).catalogs = catalogs };
5638}
5639
5640#[no_mangle]
5642pub unsafe extern "C" fn xmlCtxtGetDict(ctxt: *mut _xmlParserCtxt) -> *mut c_void {
5643 if ctxt.is_null() {
5644 return ptr::null_mut();
5645 }
5646 unsafe { (*ctxt).dict }
5647}
5648
5649#[no_mangle]
5651pub unsafe extern "C" fn xmlCtxtSetDict(ctxt: *mut _xmlParserCtxt, dict: *mut c_void) {
5652 if ctxt.is_null() {
5653 return;
5654 }
5655 unsafe {
5656 if !(*ctxt).dict.is_null() {
5657 crate::abi::exports_xml2::xmlDictFree((*ctxt).dict);
5658 }
5659 if !dict.is_null() {
5660 crate::abi::exports_hash::xmlDictReference(dict);
5661 }
5662 (*ctxt).dict = dict;
5663 }
5664}
5665
5666#[no_mangle]
5668pub unsafe extern "C" fn xmlCtxtGetSaxHandler(ctxt: *mut _xmlParserCtxt) -> *mut _xmlSAXHandler {
5669 if ctxt.is_null() {
5670 return ptr::null_mut();
5671 }
5672 unsafe { (*ctxt).sax }
5673}
5674
5675#[no_mangle]
5677pub unsafe extern "C" fn xmlCtxtSetSaxHandler(
5678 ctxt: *mut _xmlParserCtxt,
5679 sax: *const _xmlSAXHandler,
5680) -> c_int {
5681 if ctxt.is_null() || (*ctxt).sax.is_null() || sax.is_null() {
5682 return -1;
5683 }
5684 unsafe {
5685 ptr::copy_nonoverlapping(sax, (*ctxt).sax, 1);
5686 }
5687 0
5688}
5689
5690#[no_mangle]
5692pub unsafe extern "C" fn xmlCtxtIsHtml(ctxt: *mut _xmlParserCtxt) -> c_int {
5693 if ctxt.is_null() {
5694 return 0;
5695 }
5696 unsafe { (*ctxt).html }
5697}
5698
5699#[no_mangle]
5701pub unsafe extern "C" fn xmlCtxtIsStopped(ctxt: *mut _xmlParserCtxt) -> c_int {
5702 if ctxt.is_null() {
5703 return 0;
5704 }
5705 unsafe {
5706 if (*ctxt).disableSAX != 0 {
5707 1
5708 } else {
5709 0
5710 }
5711 }
5712}
5713
5714#[no_mangle]
5716pub unsafe extern "C" fn xmlCtxtIsInSubset(ctxt: *mut _xmlParserCtxt) -> c_int {
5717 if ctxt.is_null() {
5718 return 0;
5719 }
5720 unsafe { (*ctxt).inSubset }
5721}
5722
5723#[no_mangle]
5725pub unsafe extern "C" fn xmlCtxtGetValidCtxt(ctxt: *mut _xmlParserCtxt) -> *mut _xmlValidCtxt {
5726 if ctxt.is_null() {
5727 return ptr::null_mut();
5728 }
5729 unsafe { core::ptr::addr_of_mut!((*ctxt).vctxt) }
5730}
5731
5732#[no_mangle]
5734pub unsafe extern "C" fn xmlCtxtGetUserData(ctxt: *mut _xmlParserCtxt) -> *mut c_void {
5735 if ctxt.is_null() {
5736 return ptr::null_mut();
5737 }
5738 unsafe { (*ctxt).userData }
5739}
5740
5741#[no_mangle]
5743pub unsafe extern "C" fn xmlCtxtGetNode(ctxt: *mut _xmlParserCtxt) -> *mut _xmlNode {
5744 if ctxt.is_null() {
5745 return ptr::null_mut();
5746 }
5747 unsafe {
5748 if !(*ctxt).node.is_null() {
5749 (*ctxt).node
5750 } else {
5751 (*ctxt).myDoc as *mut _xmlNode
5752 }
5753 }
5754}
5755
5756#[no_mangle]
5758pub unsafe extern "C" fn xmlCtxtGetDocTypeDecl(
5759 ctxt: *mut _xmlParserCtxt,
5760 name: *mut *const xmlChar,
5761 system_id: *mut *const xmlChar,
5762 public_id: *mut *const xmlChar,
5763) -> c_int {
5764 if ctxt.is_null() {
5765 return -1;
5766 }
5767 unsafe {
5768 if !name.is_null() {
5769 *name = (*ctxt).intSubName;
5770 }
5771 if !system_id.is_null() {
5772 *system_id = (*ctxt).extSubURI as *const xmlChar;
5773 }
5774 if !public_id.is_null() {
5775 *public_id = (*ctxt).extSubSystem as *const xmlChar;
5776 }
5777 }
5778 0
5779}
5780
5781#[no_mangle]
5783pub unsafe extern "C" fn xmlCtxtGetInputPosition(
5784 ctxt: *mut _xmlParserCtxt,
5785 input_index: c_int,
5786 filename: *mut *const c_char,
5787 line: *mut c_int,
5788 col: *mut c_int,
5789 utf8_byte_pos: *mut c_ulong,
5790) -> c_int {
5791 unsafe {
5792 if ctxt.is_null() {
5793 return -1;
5794 }
5795 let mut idx = input_index;
5796 if idx < 0 {
5797 idx += (*ctxt).inputNr;
5798 if idx < 0 {
5799 return -1;
5800 }
5801 }
5802 if idx >= (*ctxt).inputNr || (*ctxt).inputTab.is_null() {
5803 return -1;
5804 }
5805 let input = *(*ctxt).inputTab.add(idx as usize);
5806 if input.is_null() {
5807 return -1;
5808 }
5809 if !filename.is_null() {
5810 *filename = (*input).filename;
5811 }
5812 if !line.is_null() {
5813 *line = (*input).line;
5814 }
5815 if !col.is_null() {
5816 *col = (*input).col;
5817 }
5818 if !utf8_byte_pos.is_null() {
5819 let consumed = (*input).consumed;
5820 let mut pos: c_ulong = consumed;
5821 if !(*input).cur.is_null() && !(*input).base.is_null() {
5822 pos = pos.wrapping_add(((*input).cur as usize - (*input).base as usize) as c_ulong);
5823 }
5824 *utf8_byte_pos = pos;
5825 }
5826 0
5827 }
5828}
5829
5830#[no_mangle]
5833pub unsafe extern "C" fn xmlCtxtGetInputWindow(
5834 ctxt: *mut _xmlParserCtxt,
5835 input_index: c_int,
5836 start_out: *mut *const xmlChar,
5837 size_in_out: *mut c_int,
5838 offset_out: *mut c_int,
5839) -> c_int {
5840 unsafe {
5841 if ctxt.is_null() || start_out.is_null() || size_in_out.is_null() || offset_out.is_null() {
5842 return -1;
5843 }
5844 let mut idx = input_index;
5845 if idx < 0 {
5846 idx += (*ctxt).inputNr;
5847 if idx < 0 {
5848 return -1;
5849 }
5850 }
5851 if idx >= (*ctxt).inputNr || (*ctxt).inputTab.is_null() {
5852 return -1;
5853 }
5854 let input = *(*ctxt).inputTab.add(idx as usize);
5855 if input.is_null() {
5856 return -1;
5857 }
5858 crate::abi::exports_misc::parser_input_get_window_pub(
5859 input,
5860 start_out,
5861 size_in_out,
5862 offset_out,
5863 );
5864 0
5865 }
5866}
5867
5868#[no_mangle]
5870pub unsafe extern "C" fn xmlCtxtGetStatus(ctxt: *mut _xmlParserCtxt) -> c_int {
5871 unsafe {
5872 let mut bits: c_int = 0;
5873 if pi_ctxt_is_catastrophic(ctxt) != 0 {
5874 bits |= 1 << 3; bits |= 1 << 0; bits |= 1 << 1; if !ctxt.is_null() && (*ctxt).validate != 0 {
5878 bits |= 1 << 2; }
5880 return bits;
5881 }
5882 if (*ctxt).wellFormed == 0 {
5883 bits |= 1 << 0;
5884 }
5885 if (*ctxt).nsWellFormed == 0 {
5886 bits |= 1 << 1;
5887 }
5888 if (*ctxt).validate != 0 && (*ctxt).valid == 0 {
5889 bits |= 1 << 2;
5890 }
5891 bits
5892 }
5893}
5894
5895#[no_mangle]
5897pub unsafe extern "C" fn xmlCtxtGetDeclaredEncoding(ctxt: *mut _xmlParserCtxt) -> *const xmlChar {
5898 if ctxt.is_null() {
5899 return ptr::null();
5900 }
5901 unsafe { (*ctxt).encoding as *const xmlChar }
5902}
5903
5904#[no_mangle]
5906pub unsafe extern "C" fn xmlCtxtGetDocument(ctxt: *mut _xmlParserCtxt) -> *mut _xmlDoc {
5907 unsafe {
5908 if ctxt.is_null() {
5909 return ptr::null_mut();
5910 }
5911 let doc: *mut _xmlDoc;
5912 if (*ctxt).wellFormed != 0
5913 || (((*ctxt).recovery != 0 || (*ctxt).html != 0) && pi_ctxt_is_catastrophic(ctxt) == 0)
5914 {
5915 doc = (*ctxt).myDoc;
5916 } else {
5917 if (*ctxt).errNo == crate::abi::types::XML_ERR_OK {
5918 (*ctxt).errNo = crate::abi::types::XML_ERR_INTERNAL_ERROR;
5920 }
5921 doc = ptr::null_mut();
5922 if !(*ctxt).myDoc.is_null() {
5923 crate::xml::tree::free_doc((*ctxt).myDoc);
5924 }
5925 }
5926 (*ctxt).myDoc = ptr::null_mut();
5927 doc
5928 }
5929}
5930
5931#[no_mangle]
5933pub unsafe extern "C" fn xmlCtxtSetCharEncConvImpl(
5934 ctxt: *mut _xmlParserCtxt,
5935 impl_: Option<crate::abi::callbacks::xmlCharEncConvImpl>,
5936 vctxt: *mut c_void,
5937) {
5938 if ctxt.is_null() {
5939 return;
5940 }
5941 unsafe {
5942 (*ctxt).convImpl = impl_;
5943 (*ctxt).convCtxt = vctxt;
5944 }
5945}
5946
5947#[no_mangle]
5949pub unsafe extern "C" fn xmlCtxtSetResourceLoader(
5950 ctxt: *mut _xmlParserCtxt,
5951 loader: Option<crate::abi::callbacks::xmlResourceLoader>,
5952 vctxt: *mut c_void,
5953) {
5954 if ctxt.is_null() {
5955 return;
5956 }
5957 unsafe {
5958 (*ctxt).resourceLoader = loader;
5959 (*ctxt).resourceCtxt = vctxt;
5960 }
5961}
5962
5963#[no_mangle]
5965pub unsafe extern "C" fn xmlCtxtPushInput(
5966 ctxt: *mut _xmlParserCtxt,
5967 value: *mut _xmlParserInput,
5968) -> c_int {
5969 unsafe {
5970 if ctxt.is_null() || value.is_null() {
5971 return -1;
5972 }
5973 let max_depth = if (*ctxt).options & crate::abi::types::XML_PARSE_HUGE != 0 {
5974 40
5975 } else {
5976 20
5977 };
5978 if (*ctxt).inputNr >= (*ctxt).inputMax {
5979 let old_max = (*ctxt).inputMax;
5980 let mut new_size = old_max * 2 + 5;
5981 if new_size > max_depth {
5982 new_size = max_depth;
5983 }
5984 if new_size <= old_max {
5985 return -1;
5986 }
5987 let tmp = xmlReallocImpl(
5988 (*ctxt).inputTab as *mut c_void,
5989 (new_size as usize) * size_of::<*mut _xmlParserInput>(),
5990 ) as *mut *mut _xmlParserInput;
5991 if tmp.is_null() {
5992 return -1;
5993 }
5994 (*ctxt).inputTab = tmp;
5995 (*ctxt).inputMax = new_size;
5996 }
5997 *(*ctxt).inputTab.add((*ctxt).inputNr as usize) = value;
5998 (*ctxt).input = value;
5999 (*value).id = (*ctxt).input_id;
6000 (*ctxt).input_id += 1;
6001 let idx = (*ctxt).inputNr;
6002 (*ctxt).inputNr += 1;
6003 idx
6004 }
6005}
6006
6007#[no_mangle]
6009pub unsafe extern "C" fn xmlCtxtPopInput(ctxt: *mut _xmlParserCtxt) -> *mut _xmlParserInput {
6010 unsafe {
6011 if ctxt.is_null() || (*ctxt).inputNr <= 0 {
6012 return ptr::null_mut();
6013 }
6014 (*ctxt).inputNr -= 1;
6015 if (*ctxt).inputNr > 0 {
6016 (*ctxt).input = *(*ctxt).inputTab.add(((*ctxt).inputNr - 1) as usize);
6017 } else {
6018 (*ctxt).input = ptr::null_mut();
6019 }
6020 let ret = *(*ctxt).inputTab.add((*ctxt).inputNr as usize);
6021 *(*ctxt).inputTab.add((*ctxt).inputNr as usize) = ptr::null_mut();
6022 ret
6023 }
6024}
6025
6026#[no_mangle]
6029pub unsafe extern "C" fn xmlCtxtValidateDtd(
6030 ctxt: *mut _xmlParserCtxt,
6031 doc: *mut _xmlDoc,
6032 dtd: *mut _xmlDtd,
6033) -> c_int {
6034 if ctxt.is_null() || (*ctxt).html != 0 {
6035 return 0;
6036 }
6037 unsafe {
6038 crate::abi::exports_parser::xmlCtxtReset(ctxt);
6039 crate::xml::validation::validate_dtd(&mut (*ctxt).vctxt, doc, dtd)
6040 }
6041}
6042
6043#[no_mangle]
6046pub unsafe extern "C" fn xmlCtxtValidateDocument(
6047 ctxt: *mut _xmlParserCtxt,
6048 doc: *mut _xmlDoc,
6049) -> c_int {
6050 if ctxt.is_null() || (*ctxt).html != 0 {
6051 return 0;
6052 }
6053 unsafe {
6054 crate::abi::exports_parser::xmlCtxtReset(ctxt);
6055 crate::xml::validation::validate_document(&mut (*ctxt).vctxt, doc)
6056 }
6057}
6058
6059#[no_mangle]
6061pub unsafe extern "C" fn xmlCtxtParseDtd(
6062 ctxt: *mut _xmlParserCtxt,
6063 input: *mut _xmlParserInput,
6064 public_id: *const xmlChar,
6065 system_id: *const xmlChar,
6066) -> *mut _xmlDtd {
6067 unsafe {
6068 if ctxt.is_null() || input.is_null() {
6069 crate::xml::parser::helpers::free_parser_input(input);
6070 return ptr::null_mut();
6071 }
6072 if xmlCtxtPushInput(ctxt, input) < 0 {
6073 crate::xml::parser::helpers::free_parser_input(input);
6074 return ptr::null_mut();
6075 }
6076 let pub_id = if public_id.is_null() {
6077 c"none".as_ptr() as *const xmlChar
6078 } else {
6079 public_id
6080 };
6081 let sys_id = if system_id.is_null() {
6082 c"none".as_ptr() as *const xmlChar
6083 } else {
6084 system_id
6085 };
6086 (*ctxt).myDoc = crate::xml::tree::new_doc(c"1.0".as_ptr() as *const xmlChar);
6087 if (*ctxt).myDoc.is_null() {
6088 return ptr::null_mut();
6089 }
6090 (*(*ctxt).myDoc).properties = XML_DOC_INTERNAL as c_int;
6091 (*(*ctxt).myDoc).extSubset = crate::xml::tree::new_dtd(
6092 (*ctxt).myDoc,
6093 c"none".as_ptr() as *const xmlChar,
6094 pub_id,
6095 sys_id,
6096 );
6097 if (*(*ctxt).myDoc).extSubset.is_null() {
6098 crate::xml::tree::free_doc((*ctxt).myDoc);
6099 (*ctxt).myDoc = ptr::null_mut();
6100 return ptr::null_mut();
6101 }
6102 pi_parse_external_subset(ctxt, pub_id, sys_id);
6103 let mut ret: *mut _xmlDtd = ptr::null_mut();
6104 if (*ctxt).wellFormed != 0 {
6105 ret = (*(*ctxt).myDoc).extSubset;
6106 (*(*ctxt).myDoc).extSubset = ptr::null_mut();
6107 if !ret.is_null() {
6108 (*ret).doc = ptr::null_mut();
6109 let mut tmp = (*ret).children;
6110 while !tmp.is_null() {
6111 (*tmp).doc = ptr::null_mut();
6112 tmp = (*tmp).next;
6113 }
6114 }
6115 }
6116 if !(*ctxt).myDoc.is_null() {
6117 crate::xml::tree::free_doc((*ctxt).myDoc);
6118 }
6119 (*ctxt).myDoc = ptr::null_mut();
6120 ret
6121 }
6122}
6123
6124#[no_mangle]
6128pub unsafe extern "C" fn xmlCtxtParseContent(
6129 ctxt: *mut _xmlParserCtxt,
6130 input: *mut _xmlParserInput,
6131 node: *mut _xmlNode,
6132 has_text_decl: c_int,
6133) -> *mut _xmlNode {
6134 unsafe {
6135 if ctxt.is_null() || input.is_null() || node.is_null() {
6136 crate::xml::parser::helpers::free_parser_input(input);
6137 return ptr::null_mut();
6138 }
6139 let doc = (*node).doc;
6140 if doc.is_null() {
6141 crate::xml::parser::helpers::free_parser_input(input);
6142 return ptr::null_mut();
6143 }
6144 let mut target = node;
6145 match (*node).type_ {
6146 t if t == xmlElementType::XML_ELEMENT_NODE as c_int
6147 || t == xmlElementType::XML_DOCUMENT_NODE as c_int
6148 || t == xmlElementType::XML_HTML_DOCUMENT_NODE as c_int => {}
6149 t if t == xmlElementType::XML_ATTRIBUTE_NODE as c_int
6150 || t == xmlElementType::XML_TEXT_NODE as c_int
6151 || t == xmlElementType::XML_CDATA_SECTION_NODE as c_int
6152 || t == xmlElementType::XML_ENTITY_REF_NODE as c_int
6153 || t == xmlElementType::XML_PI_NODE as c_int
6154 || t == xmlElementType::XML_COMMENT_NODE as c_int =>
6155 {
6156 let mut cur = (*node).parent;
6157 while !cur.is_null() {
6158 let ct = (*cur).type_;
6159 if ct == xmlElementType::XML_ELEMENT_NODE as c_int
6160 || ct == xmlElementType::XML_DOCUMENT_NODE as c_int
6161 || ct == xmlElementType::XML_HTML_DOCUMENT_NODE as c_int
6162 {
6163 target = cur;
6164 break;
6165 }
6166 cur = (*cur).parent;
6167 }
6168 }
6169 _ => {
6170 crate::xml::parser::helpers::free_parser_input(input);
6171 return ptr::null_mut();
6172 }
6173 }
6174
6175 crate::abi::exports_parser::xmlCtxtReset(ctxt);
6176 let old_dict = (*ctxt).dict;
6177 let old_options = (*ctxt).options;
6178 let old_dict_names = (*ctxt).dictNames;
6179 let old_load_subset = (*ctxt).loadsubset;
6180 if !(*doc).dict.is_null() {
6181 (*ctxt).dict = (*doc).dict;
6182 } else {
6183 (*ctxt).options |= crate::abi::types::XML_PARSE_NODICT;
6184 (*ctxt).dictNames = 0;
6185 }
6186 (*ctxt).loadsubset |= crate::abi::constants::XML_SKIP_IDS;
6187 (*ctxt).options |= crate::abi::types::XML_PARSE_SKIP_IDS;
6188 (*ctxt).myDoc = doc;
6189
6190 let list = pi_parse_content_node_list(ctxt, input, has_text_decl);
6191
6192 (*ctxt).dict = old_dict;
6193 (*ctxt).options = old_options;
6194 (*ctxt).dictNames = old_dict_names;
6195 (*ctxt).loadsubset = old_load_subset;
6196 (*ctxt).myDoc = ptr::null_mut();
6197 (*ctxt).node = ptr::null_mut();
6198 crate::xml::parser::helpers::free_parser_input(input);
6199 let _ = target;
6200 list
6201 }
6202}
6203
6204unsafe fn pi_set_input_filename(input: *mut _xmlParserInput, url: *const c_char) {
6215 if !url.is_null() {
6216 (*input).filename = crate::xml::string::xml_strdup(url as *const crate::abi::types::xmlChar)
6217 as *const c_char;
6218 }
6219}
6220
6221#[no_mangle]
6223pub unsafe extern "C" fn xmlNewInputFromMemory(
6224 url: *const c_char,
6225 mem: *const c_void,
6226 size: usize,
6227 _flags: c_int,
6228) -> *mut _xmlParserInput {
6229 unsafe {
6230 if mem.is_null() {
6231 return ptr::null_mut();
6232 }
6233 let buf = crate::xml::io::input_buffer_create_mem(
6234 mem as *const c_char,
6235 size as c_int,
6236 crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_NONE as c_int,
6237 );
6238 if buf.is_null() {
6239 return ptr::null_mut();
6240 }
6241 let input = crate::abi::exports_parser::parser_input_from_buf_pub(buf);
6242 if input.is_null() {
6243 return ptr::null_mut();
6244 }
6245 pi_set_input_filename(input, url);
6246 input
6247 }
6248}
6249
6250#[no_mangle]
6252pub unsafe extern "C" fn xmlNewInputFromString(
6253 url: *const c_char,
6254 str: *const c_char,
6255 _flags: c_int,
6256) -> *mut _xmlParserInput {
6257 unsafe {
6258 if str.is_null() {
6259 return ptr::null_mut();
6260 }
6261 let len = libc::strlen(str);
6262 let buf = crate::xml::io::input_buffer_create_mem(
6263 str,
6264 len as c_int,
6265 crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_NONE as c_int,
6266 );
6267 if buf.is_null() {
6268 return ptr::null_mut();
6269 }
6270 let input = crate::abi::exports_parser::parser_input_from_buf_pub(buf);
6271 if input.is_null() {
6272 return ptr::null_mut();
6273 }
6274 pi_set_input_filename(input, url);
6275 input
6276 }
6277}
6278
6279#[no_mangle]
6283pub unsafe extern "C" fn xmlNewInputFromFd(
6284 url: *const c_char,
6285 fd: c_int,
6286 _flags: c_int,
6287) -> *mut _xmlParserInput {
6288 unsafe {
6289 if fd < 0 {
6290 return ptr::null_mut();
6291 }
6292 let mut data: Vec<u8> = Vec::new();
6293 let mut tmp = [0u8; 4096];
6294 loop {
6295 let n = libc::read(fd, tmp.as_mut_ptr() as *mut c_void, tmp.len());
6296 if n <= 0 {
6297 break;
6298 }
6299 data.extend_from_slice(&tmp[..n as usize]);
6300 }
6301 let buf = crate::xml::io::input_buffer_create_mem(
6302 data.as_ptr() as *const c_char,
6303 data.len() as c_int,
6304 crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_NONE as c_int,
6305 );
6306 if buf.is_null() {
6307 return ptr::null_mut();
6308 }
6309 let input = crate::abi::exports_parser::parser_input_from_buf_pub(buf);
6310 if input.is_null() {
6311 return ptr::null_mut();
6312 }
6313 pi_set_input_filename(input, url);
6314 input
6315 }
6316}
6317
6318#[no_mangle]
6320pub unsafe extern "C" fn xmlNewInputFromIO(
6321 url: *const c_char,
6322 io_read: Option<crate::abi::callbacks::xmlInputReadCallback>,
6323 io_close: Option<crate::abi::callbacks::xmlInputCloseCallback>,
6324 io_ctxt: *mut c_void,
6325 _flags: c_int,
6326) -> *mut _xmlParserInput {
6327 unsafe {
6328 let Some(read) = io_read else {
6329 return ptr::null_mut();
6330 };
6331 let mut data: Vec<u8> = Vec::new();
6333 let mut tmp = [0u8; 4096];
6334 loop {
6335 let n = read(io_ctxt, tmp.as_mut_ptr() as *mut c_char, tmp.len() as c_int);
6336 if n <= 0 {
6337 break;
6338 }
6339 data.extend_from_slice(&tmp[..n as usize]);
6340 }
6341 let buf = crate::xml::io::input_buffer_create_mem(
6342 data.as_ptr() as *const c_char,
6343 data.len() as c_int,
6344 crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_NONE as c_int,
6345 );
6346 if buf.is_null() {
6347 if let Some(close) = io_close {
6348 close(io_ctxt);
6349 }
6350 return ptr::null_mut();
6351 }
6352 (*buf).closecallback = io_close;
6354 let input = crate::abi::exports_parser::parser_input_from_buf_pub(buf);
6355 if input.is_null() {
6356 return ptr::null_mut();
6357 }
6358 pi_set_input_filename(input, url);
6359 input
6360 }
6361}
6362
6363#[no_mangle]
6366pub unsafe extern "C" fn xmlNewInputFromUrl(
6367 url: *const c_char,
6368 _flags: c_int,
6369 out: *mut *mut _xmlParserInput,
6370) -> c_int {
6371 unsafe {
6372 if out.is_null() {
6373 return crate::abi::types::XML_ERR_ARGUMENT;
6374 }
6375 *out = ptr::null_mut();
6376 if url.is_null() {
6377 return crate::abi::types::XML_ERR_ARGUMENT;
6378 }
6379 let buf = crate::xml::io::input_buffer_create_file(
6380 url,
6381 crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_NONE as c_int,
6382 );
6383 if buf.is_null() {
6384 return crate::abi::types::XML_IO_ENOENT;
6385 }
6386 let input = crate::abi::exports_parser::parser_input_from_buf_pub(buf);
6387 if input.is_null() {
6388 return crate::abi::types::XML_ERR_NO_MEMORY;
6389 }
6390 pi_set_input_filename(input, url);
6391 *out = input;
6392 crate::abi::types::XML_ERR_OK
6393 }
6394}
6395
6396#[no_mangle]
6399pub unsafe extern "C" fn xmlInputSetEncodingHandler(
6400 input: *mut _xmlParserInput,
6401 handler: *mut c_void,
6402) -> c_int {
6403 unsafe {
6404 if input.is_null() || (*input).buf.is_null() {
6405 if !handler.is_null() {
6406 crate::abi::exports_xml2::xmlCharEncCloseFunc(handler);
6407 }
6408 return crate::abi::types::XML_ERR_ARGUMENT;
6409 }
6410 let in_ = (*input).buf;
6411 let mut h = handler;
6412 if !h.is_null() {
6414 let name = (*(h as *mut crate::abi::structs::_xmlCharEncodingHandler)).name;
6415 if !name.is_null()
6416 && crate::abi::exports_xml2::xmlStrcasecmp(
6417 name as *const crate::abi::types::xmlChar,
6418 c"UTF-8".as_ptr() as *const crate::abi::types::xmlChar,
6419 ) == 0
6420 {
6421 crate::abi::exports_xml2::xmlCharEncCloseFunc(h);
6422 h = ptr::null_mut();
6423 }
6424 }
6425 if std::ptr::eq((*in_).encoder, h) {
6426 return crate::abi::types::XML_ERR_OK;
6427 }
6428 if !(*in_).encoder.is_null() {
6429 crate::abi::exports_xml2::xmlCharEncCloseFunc((*in_).encoder);
6430 (*in_).encoder = h;
6431 return crate::abi::types::XML_ERR_OK;
6432 }
6433 (*in_).encoder = h;
6434 crate::abi::types::XML_ERR_OK
6435 }
6436}