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