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