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