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