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