1#![allow(
95 missing_docs,
96 non_snake_case,
97 non_camel_case_types,
98 non_upper_case_globals
99)]
100#![allow(unused_variables)]
101#![allow(private_interfaces)]
102#![allow(unused_assignments)]
103#![allow(unused_unsafe)]
104#![allow(clippy::missing_safety_doc)]
105#![allow(clippy::not_unsafe_ptr_arg_deref)]
106
107use core::ffi::c_void;
108use core::ptr;
109use core::sync::atomic::{AtomicBool, AtomicI32, Ordering};
110use std::mem::size_of;
111use std::os::raw::{c_char, c_int, c_uint};
112
113use crate::abi::allocator::{xmlFreeImpl, xmlMallocImpl, xmlMallocZero, xmlReallocImpl};
114use crate::abi::callbacks::{xmlInputCloseCallback, xmlInputReadCallback};
115use crate::abi::structs::*;
116use crate::abi::types::xmlChar;
117use crate::abi::types::xmlCharEncoding;
118use crate::abi::types::xmlElementType::*;
119use crate::xml::html;
120use crate::xml::io;
121use crate::xml::string::{c_strdup, xml_strcmp, xml_strlen, xml_strndup, xmlstr_to_bytes};
122use crate::xml::tree;
123
124const HTML_PARSE_RECOVER: c_int = 1 << 0;
129const HTML_PARSE_NODEFDTD: c_int = 1 << 2;
130const HTML_PARSE_NOERROR: c_int = 1 << 5;
131const HTML_PARSE_NOWARNING: c_int = 1 << 6;
132const HTML_PARSE_PEDANTIC: c_int = 1 << 7;
133const HTML_PARSE_NOBLANKS: c_int = 1 << 8;
134const HTML_PARSE_NONET: c_int = 1 << 11;
135const HTML_PARSE_NOIMPLIED: c_int = 1 << 13;
136const HTML_PARSE_COMPACT: c_int = 1 << 16;
137const HTML_PARSE_HUGE: c_int = 1 << 19;
138const HTML_PARSE_IGNORE_ENC: c_int = 1 << 21;
139const HTML_PARSE_BIG_LINES: c_int = 1 << 22;
140const HTML_PARSE_HTML5: c_int = 1 << 26;
141
142const HTML_OPTIONS_KEEP_MASK: c_int = HTML_PARSE_NODEFDTD
144 | HTML_PARSE_NOERROR
145 | HTML_PARSE_NOWARNING
146 | HTML_PARSE_NOIMPLIED
147 | HTML_PARSE_COMPACT
148 | HTML_PARSE_HUGE
149 | HTML_PARSE_IGNORE_ENC
150 | HTML_PARSE_BIG_LINES;
151
152const HTML_OPTIONS_ALL_MASK: c_int = HTML_PARSE_RECOVER
154 | HTML_PARSE_HTML5
155 | HTML_PARSE_NODEFDTD
156 | HTML_PARSE_NOERROR
157 | HTML_PARSE_NOWARNING
158 | HTML_PARSE_PEDANTIC
159 | HTML_PARSE_NOBLANKS
160 | HTML_PARSE_NONET
161 | HTML_PARSE_NOIMPLIED
162 | HTML_PARSE_COMPACT
163 | HTML_PARSE_HUGE
164 | HTML_PARSE_IGNORE_ENC
165 | HTML_PARSE_BIG_LINES;
166
167const XML_ERR_OK: c_int = 0;
169const XML_ERR_NO_MEMORY: c_int = 2;
170const XML_ERR_ARGUMENT: c_int = 115;
171
172const HTML_VALID: c_int = 0x4;
174
175const DATA_NEUTRAL: c_int = 0;
177const DATA_RCDATA: c_int = 1;
178const DATA_RAWTEXT: c_int = 2;
179const DATA_PLAINTEXT: c_int = 3;
180const DATA_SCRIPT: c_int = 4;
181
182#[inline]
184const fn is_ws_html(c: u8) -> bool {
185 c == 0x20 || (c >= 0x09 && c <= 0x0d && c != 0x0b)
186}
187
188#[derive(Debug)]
197#[repr(C)]
198pub struct _htmlElemDesc {
199 pub name: *const c_char,
200 pub startTag: c_char,
201 pub endTag: c_char,
202 pub saveEndTag: c_char,
203 pub empty: c_char,
204 pub depr: c_char,
205 pub dtd: c_char,
206 pub isinline: c_char,
207 pub desc: *const c_char,
208 pub subelts: *const *const c_char,
209 pub defaultsubelt: *const c_char,
210 pub attrs_opt: *const *const c_char,
211 pub attrs_depr: *const *const c_char,
212 pub attrs_req: *const *const c_char,
213 pub dataMode: c_int,
214}
215
216unsafe impl Sync for _htmlElemDesc {}
218unsafe impl Send for _htmlElemDesc {}
219
220macro_rules! elem {
224 ($name:literal, $startTag:expr, $endTag:expr, $saveEndTag:expr, $empty:expr, $depr:expr, $dtd:expr, $isinline:expr, $desc:literal, $dataMode:expr) => {
225 _htmlElemDesc {
226 name: concat!($name, "\0").as_ptr() as *const c_char,
227 startTag: $startTag,
228 endTag: $endTag,
229 saveEndTag: $saveEndTag,
230 empty: $empty,
231 depr: $depr,
232 dtd: $dtd,
233 isinline: $isinline,
234 desc: concat!($desc, "\0").as_ptr() as *const c_char,
235 subelts: ptr::null(),
236 defaultsubelt: ptr::null(),
237 attrs_opt: ptr::null(),
238 attrs_depr: ptr::null(),
239 attrs_req: ptr::null(),
240 dataMode: $dataMode,
241 }
242 };
243}
244
245static HTML40_ELEMENTS: &[_htmlElemDesc] = &[
248 elem!("a", 0, 0, 0, 0, 0, 0, 1, "anchor ", DATA_NEUTRAL),
249 elem!(
250 "abbr",
251 0,
252 0,
253 0,
254 0,
255 0,
256 0,
257 1,
258 "abbreviated form",
259 DATA_NEUTRAL
260 ),
261 elem!("acronym", 0, 0, 0, 0, 0, 0, 1, "", DATA_NEUTRAL),
262 elem!(
263 "address",
264 0,
265 0,
266 0,
267 0,
268 0,
269 0,
270 0,
271 "information on author ",
272 DATA_NEUTRAL
273 ),
274 elem!("applet", 0, 0, 0, 0, 1, 1, 2, "java applet ", DATA_NEUTRAL),
275 elem!(
276 "area",
277 0,
278 2,
279 2,
280 1,
281 0,
282 0,
283 0,
284 "client-side image map area ",
285 DATA_NEUTRAL
286 ),
287 elem!("b", 0, 3, 0, 0, 0, 0, 1, "bold text style", DATA_NEUTRAL),
288 elem!(
289 "base",
290 0,
291 2,
292 2,
293 1,
294 0,
295 0,
296 0,
297 "document base uri ",
298 DATA_NEUTRAL
299 ),
300 elem!(
301 "basefont",
302 0,
303 2,
304 2,
305 1,
306 1,
307 1,
308 1,
309 "base font size ",
310 DATA_NEUTRAL
311 ),
312 elem!(
313 "bdo",
314 0,
315 0,
316 0,
317 0,
318 0,
319 0,
320 1,
321 "i18n bidi over-ride ",
322 DATA_NEUTRAL
323 ),
324 elem!("bgsound", 0, 0, 2, 1, 0, 0, 0, "", DATA_NEUTRAL),
325 elem!("big", 0, 3, 0, 0, 0, 0, 1, "large text style", DATA_NEUTRAL),
326 elem!(
327 "blockquote",
328 0,
329 0,
330 0,
331 0,
332 0,
333 0,
334 0,
335 "long quotation ",
336 DATA_NEUTRAL
337 ),
338 elem!("body", 1, 1, 0, 0, 0, 0, 0, "document body ", DATA_NEUTRAL),
339 elem!(
340 "br",
341 0,
342 2,
343 2,
344 1,
345 0,
346 0,
347 1,
348 "forced line break ",
349 DATA_NEUTRAL
350 ),
351 elem!("button", 0, 0, 0, 0, 0, 0, 2, "push button ", DATA_NEUTRAL),
352 elem!(
353 "caption",
354 0,
355 0,
356 0,
357 0,
358 0,
359 0,
360 0,
361 "table caption ",
362 DATA_NEUTRAL
363 ),
364 elem!(
365 "center",
366 0,
367 3,
368 0,
369 0,
370 1,
371 1,
372 0,
373 "shorthand for div align=center ",
374 DATA_NEUTRAL
375 ),
376 elem!("cite", 0, 0, 0, 0, 0, 0, 1, "citation", DATA_NEUTRAL),
377 elem!(
378 "code",
379 0,
380 0,
381 0,
382 0,
383 0,
384 0,
385 1,
386 "computer code fragment",
387 DATA_NEUTRAL
388 ),
389 elem!("col", 0, 2, 2, 1, 0, 0, 0, "table column ", DATA_NEUTRAL),
390 elem!(
391 "colgroup",
392 0,
393 1,
394 0,
395 0,
396 0,
397 0,
398 0,
399 "table column group ",
400 DATA_NEUTRAL
401 ),
402 elem!(
403 "dd",
404 0,
405 1,
406 0,
407 0,
408 0,
409 0,
410 0,
411 "definition description ",
412 DATA_NEUTRAL
413 ),
414 elem!("del", 0, 0, 0, 0, 0, 0, 2, "deleted text ", DATA_NEUTRAL),
415 elem!(
416 "dfn",
417 0,
418 0,
419 0,
420 0,
421 0,
422 0,
423 1,
424 "instance definition",
425 DATA_NEUTRAL
426 ),
427 elem!("dir", 0, 0, 0, 0, 1, 1, 0, "directory list", DATA_NEUTRAL),
428 elem!(
429 "div",
430 0,
431 0,
432 0,
433 0,
434 0,
435 0,
436 0,
437 "generic language/style container",
438 DATA_NEUTRAL
439 ),
440 elem!("dl", 0, 0, 0, 0, 0, 0, 0, "definition list ", DATA_NEUTRAL),
441 elem!("dt", 0, 1, 0, 0, 0, 0, 0, "definition term ", DATA_NEUTRAL),
442 elem!("em", 0, 3, 0, 0, 0, 0, 1, "emphasis", DATA_NEUTRAL),
443 elem!(
444 "embed",
445 0,
446 1,
447 2,
448 1,
449 1,
450 1,
451 1,
452 "generic embedded object ",
453 DATA_NEUTRAL
454 ),
455 elem!(
456 "fieldset",
457 0,
458 0,
459 0,
460 0,
461 0,
462 0,
463 0,
464 "form control group ",
465 DATA_NEUTRAL
466 ),
467 elem!(
468 "font",
469 0,
470 3,
471 0,
472 0,
473 1,
474 1,
475 1,
476 "local change to font ",
477 DATA_NEUTRAL
478 ),
479 elem!(
480 "form",
481 0,
482 0,
483 0,
484 0,
485 0,
486 0,
487 0,
488 "interactive form ",
489 DATA_NEUTRAL
490 ),
491 elem!("frame", 0, 2, 2, 1, 0, 2, 0, "subwindow ", DATA_NEUTRAL),
492 elem!(
493 "frameset",
494 0,
495 0,
496 0,
497 0,
498 0,
499 2,
500 0,
501 "window subdivision",
502 DATA_NEUTRAL
503 ),
504 elem!("h1", 0, 0, 0, 0, 0, 0, 0, "heading ", DATA_NEUTRAL),
505 elem!("h2", 0, 0, 0, 0, 0, 0, 0, "heading ", DATA_NEUTRAL),
506 elem!("h3", 0, 0, 0, 0, 0, 0, 0, "heading ", DATA_NEUTRAL),
507 elem!("h4", 0, 0, 0, 0, 0, 0, 0, "heading ", DATA_NEUTRAL),
508 elem!("h5", 0, 0, 0, 0, 0, 0, 0, "heading ", DATA_NEUTRAL),
509 elem!("h6", 0, 0, 0, 0, 0, 0, 0, "heading ", DATA_NEUTRAL),
510 elem!("head", 1, 1, 0, 0, 0, 0, 0, "document head ", DATA_NEUTRAL),
511 elem!("hr", 0, 2, 2, 1, 0, 0, 0, "horizontal rule ", DATA_NEUTRAL),
512 elem!(
513 "html",
514 1,
515 1,
516 0,
517 0,
518 0,
519 0,
520 0,
521 "document root element ",
522 DATA_NEUTRAL
523 ),
524 elem!("i", 0, 3, 0, 0, 0, 0, 1, "italic text style", DATA_NEUTRAL),
525 elem!(
526 "iframe",
527 0,
528 0,
529 0,
530 0,
531 0,
532 1,
533 2,
534 "inline subwindow ",
535 DATA_RAWTEXT
536 ),
537 elem!("img", 0, 2, 2, 1, 0, 0, 1, "embedded image ", DATA_NEUTRAL),
538 elem!("input", 0, 2, 2, 1, 0, 0, 1, "form control ", DATA_NEUTRAL),
539 elem!("ins", 0, 0, 0, 0, 0, 0, 2, "inserted text", DATA_NEUTRAL),
540 elem!(
541 "isindex",
542 0,
543 2,
544 2,
545 1,
546 1,
547 1,
548 0,
549 "single line prompt ",
550 DATA_NEUTRAL
551 ),
552 elem!(
553 "kbd",
554 0,
555 0,
556 0,
557 0,
558 0,
559 0,
560 1,
561 "text to be entered by the user",
562 DATA_NEUTRAL
563 ),
564 elem!("keygen", 0, 0, 2, 1, 0, 0, 0, "", DATA_NEUTRAL),
565 elem!(
566 "label",
567 0,
568 0,
569 0,
570 0,
571 0,
572 0,
573 1,
574 "form field label text ",
575 DATA_NEUTRAL
576 ),
577 elem!(
578 "legend",
579 0,
580 0,
581 0,
582 0,
583 0,
584 0,
585 0,
586 "fieldset legend ",
587 DATA_NEUTRAL
588 ),
589 elem!("li", 0, 1, 1, 0, 0, 0, 0, "list item ", DATA_NEUTRAL),
590 elem!(
591 "link",
592 0,
593 2,
594 2,
595 1,
596 0,
597 0,
598 0,
599 "a media-independent link ",
600 DATA_NEUTRAL
601 ),
602 elem!(
603 "map",
604 0,
605 0,
606 0,
607 0,
608 0,
609 0,
610 2,
611 "client-side image map ",
612 DATA_NEUTRAL
613 ),
614 elem!("menu", 0, 0, 0, 0, 1, 1, 0, "menu list ", DATA_NEUTRAL),
615 elem!(
616 "meta",
617 0,
618 2,
619 2,
620 1,
621 0,
622 0,
623 0,
624 "generic metainformation ",
625 DATA_NEUTRAL
626 ),
627 elem!("noembed", 0, 0, 0, 0, 0, 0, 0, "", DATA_RAWTEXT),
628 elem!(
629 "noframes",
630 0,
631 0,
632 0,
633 0,
634 0,
635 2,
636 0,
637 "alternate content container for non frame-based rendering ",
638 DATA_RAWTEXT
639 ),
640 elem!(
641 "noscript",
642 0,
643 0,
644 0,
645 0,
646 0,
647 0,
648 0,
649 "alternate content container for non script-based rendering ",
650 DATA_NEUTRAL
651 ),
652 elem!(
653 "object",
654 0,
655 0,
656 0,
657 0,
658 0,
659 0,
660 2,
661 "generic embedded object ",
662 DATA_NEUTRAL
663 ),
664 elem!("ol", 0, 0, 0, 0, 0, 0, 0, "ordered list ", DATA_NEUTRAL),
665 elem!(
666 "optgroup",
667 0,
668 0,
669 0,
670 0,
671 0,
672 0,
673 0,
674 "option group ",
675 DATA_NEUTRAL
676 ),
677 elem!(
678 "option",
679 0,
680 1,
681 0,
682 0,
683 0,
684 0,
685 0,
686 "selectable choice ",
687 DATA_NEUTRAL
688 ),
689 elem!("p", 0, 1, 0, 0, 0, 0, 0, "paragraph ", DATA_NEUTRAL),
690 elem!(
691 "param",
692 0,
693 2,
694 2,
695 1,
696 0,
697 0,
698 0,
699 "named property value ",
700 DATA_NEUTRAL
701 ),
702 elem!("plaintext", 0, 0, 0, 0, 0, 0, 0, "", DATA_PLAINTEXT),
703 elem!(
704 "pre",
705 0,
706 0,
707 0,
708 0,
709 0,
710 0,
711 0,
712 "preformatted text ",
713 DATA_NEUTRAL
714 ),
715 elem!(
716 "q",
717 0,
718 0,
719 0,
720 0,
721 0,
722 0,
723 1,
724 "short inline quotation ",
725 DATA_NEUTRAL
726 ),
727 elem!(
728 "s",
729 0,
730 3,
731 0,
732 0,
733 1,
734 1,
735 1,
736 "strike-through text style",
737 DATA_NEUTRAL
738 ),
739 elem!(
740 "samp",
741 0,
742 0,
743 0,
744 0,
745 0,
746 0,
747 1,
748 "sample program output, scripts, etc.",
749 DATA_NEUTRAL
750 ),
751 elem!(
752 "script",
753 0,
754 0,
755 0,
756 0,
757 0,
758 0,
759 2,
760 "script statements ",
761 DATA_SCRIPT
762 ),
763 elem!(
764 "select",
765 0,
766 0,
767 0,
768 0,
769 0,
770 0,
771 1,
772 "option selector ",
773 DATA_NEUTRAL
774 ),
775 elem!(
776 "small",
777 0,
778 3,
779 0,
780 0,
781 0,
782 0,
783 1,
784 "small text style",
785 DATA_NEUTRAL
786 ),
787 elem!("source", 0, 0, 2, 1, 0, 0, 0, "", DATA_NEUTRAL),
788 elem!(
789 "span",
790 0,
791 0,
792 0,
793 0,
794 0,
795 0,
796 1,
797 "generic language/style container ",
798 DATA_NEUTRAL
799 ),
800 elem!(
801 "strike",
802 0,
803 3,
804 0,
805 0,
806 1,
807 1,
808 1,
809 "strike-through text",
810 DATA_NEUTRAL
811 ),
812 elem!(
813 "strong",
814 0,
815 3,
816 0,
817 0,
818 0,
819 0,
820 1,
821 "strong emphasis",
822 DATA_NEUTRAL
823 ),
824 elem!("style", 0, 0, 0, 0, 0, 0, 0, "style info ", DATA_RAWTEXT),
825 elem!("sub", 0, 3, 0, 0, 0, 0, 1, "subscript", DATA_NEUTRAL),
826 elem!("sup", 0, 3, 0, 0, 0, 0, 1, "superscript ", DATA_NEUTRAL),
827 elem!("table", 0, 0, 0, 0, 0, 0, 0, "", DATA_NEUTRAL),
828 elem!("tbody", 1, 0, 0, 0, 0, 0, 0, "table body ", DATA_NEUTRAL),
829 elem!("td", 0, 0, 0, 0, 0, 0, 0, "table data cell", DATA_NEUTRAL),
830 elem!(
831 "textarea",
832 0,
833 0,
834 0,
835 0,
836 0,
837 0,
838 1,
839 "multi-line text field ",
840 DATA_RCDATA
841 ),
842 elem!("tfoot", 0, 1, 0, 0, 0, 0, 0, "table footer ", DATA_NEUTRAL),
843 elem!("th", 0, 1, 0, 0, 0, 0, 0, "table header cell", DATA_NEUTRAL),
844 elem!("thead", 0, 1, 0, 0, 0, 0, 0, "table header ", DATA_NEUTRAL),
845 elem!("title", 0, 0, 0, 0, 0, 0, 0, "document title ", DATA_RCDATA),
846 elem!("tr", 0, 0, 0, 0, 0, 0, 0, "table row ", DATA_NEUTRAL),
847 elem!("track", 0, 0, 2, 1, 0, 0, 0, "", DATA_NEUTRAL),
848 elem!(
849 "tt",
850 0,
851 3,
852 0,
853 0,
854 0,
855 0,
856 1,
857 "teletype or monospaced text style",
858 DATA_NEUTRAL
859 ),
860 elem!(
861 "u",
862 0,
863 3,
864 0,
865 0,
866 1,
867 1,
868 1,
869 "underlined text style",
870 DATA_NEUTRAL
871 ),
872 elem!("ul", 0, 0, 0, 0, 0, 0, 0, "unordered list ", DATA_NEUTRAL),
873 elem!(
874 "var",
875 0,
876 0,
877 0,
878 0,
879 0,
880 0,
881 1,
882 "instance of a variable or program argument",
883 DATA_NEUTRAL
884 ),
885 elem!("wbr", 0, 0, 2, 1, 0, 0, 0, "", DATA_NEUTRAL),
886 elem!("xmp", 0, 0, 0, 0, 0, 0, 1, "", DATA_RAWTEXT),
887];
888
889#[no_mangle]
901pub unsafe extern "C" fn htmlTagLookup(tag: *const xmlChar) -> *const _htmlElemDesc {
902 if tag.is_null() {
903 return ptr::null();
904 }
905 let bytes = unsafe { xmlstr_to_bytes(tag) };
906 for e in HTML40_ELEMENTS {
907 let name = unsafe { core::ffi::CStr::from_ptr(e.name) }.to_bytes();
908 if bytes.eq_ignore_ascii_case(name) {
909 return e as *const _htmlElemDesc;
910 }
911 }
912 ptr::null()
913}
914
915#[derive(Debug)]
921#[repr(C)]
922pub struct _htmlEntityDesc {
923 pub value: c_uint,
924 pub name: *const c_char,
925 pub desc: *const c_char,
926}
927
928unsafe impl Sync for _htmlEntityDesc {}
930unsafe impl Send for _htmlEntityDesc {}
931
932macro_rules! ent {
934 ($value:expr, $name:literal, $desc:literal) => {
935 _htmlEntityDesc {
936 value: $value,
937 name: concat!($name, "\0").as_ptr() as *const c_char,
938 desc: concat!($desc, "\0").as_ptr() as *const c_char,
939 }
940 };
941}
942
943static HTML40_ENTITIES: &[_htmlEntityDesc] = &[
947 ent!(34, "quot", "quotation mark = APL quote, U+0022 ISOnum"),
948 ent!(38, "amp", "ampersand, U+0026 ISOnum"),
949 ent!(39, "apos", "single quote"),
950 ent!(60, "lt", "less-than sign, U+003C ISOnum"),
951 ent!(62, "gt", "greater-than sign, U+003E ISOnum"),
952 ent!(
953 160,
954 "nbsp",
955 "no-break space = non-breaking space, U+00A0 ISOnum"
956 ),
957 ent!(161, "iexcl", "inverted exclamation mark, U+00A1 ISOnum"),
958 ent!(162, "cent", "cent sign, U+00A2 ISOnum"),
959 ent!(163, "pound", "pound sign, U+00A3 ISOnum"),
960 ent!(164, "curren", "currency sign, U+00A4 ISOnum"),
961 ent!(165, "yen", "yen sign = yuan sign, U+00A5 ISOnum"),
962 ent!(
963 166,
964 "brvbar",
965 "broken bar = broken vertical bar, U+00A6 ISOnum"
966 ),
967 ent!(167, "sect", "section sign, U+00A7 ISOnum"),
968 ent!(168, "uml", "diaeresis = spacing diaeresis, U+00A8 ISOdia"),
969 ent!(169, "copy", "copyright sign, U+00A9 ISOnum"),
970 ent!(170, "ordf", "feminine ordinal indicator, U+00AA ISOnum"),
971 ent!(
972 171,
973 "laquo",
974 "left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum"
975 ),
976 ent!(172, "not", "not sign, U+00AC ISOnum"),
977 ent!(
978 173,
979 "shy",
980 "soft hyphen = discretionary hyphen, U+00AD ISOnum"
981 ),
982 ent!(
983 174,
984 "reg",
985 "registered sign = registered trade mark sign, U+00AE ISOnum"
986 ),
987 ent!(
988 175,
989 "macr",
990 "macron = spacing macron = overline = APL overbar, U+00AF ISOdia"
991 ),
992 ent!(176, "deg", "degree sign, U+00B0 ISOnum"),
993 ent!(
994 177,
995 "plusmn",
996 "plus-minus sign = plus-or-minus sign, U+00B1 ISOnum"
997 ),
998 ent!(
999 178,
1000 "sup2",
1001 "superscript two = superscript digit two = squared, U+00B2 ISOnum"
1002 ),
1003 ent!(
1004 179,
1005 "sup3",
1006 "superscript three = superscript digit three = cubed, U+00B3 ISOnum"
1007 ),
1008 ent!(180, "acute", "acute accent = spacing acute, U+00B4 ISOdia"),
1009 ent!(181, "micro", "micro sign, U+00B5 ISOnum"),
1010 ent!(182, "para", "pilcrow sign = paragraph sign, U+00B6 ISOnum"),
1011 ent!(
1012 183,
1013 "middot",
1014 "middle dot = Georgian comma Greek middle dot, U+00B7 ISOnum"
1015 ),
1016 ent!(184, "cedil", "cedilla = spacing cedilla, U+00B8 ISOdia"),
1017 ent!(
1018 185,
1019 "sup1",
1020 "superscript one = superscript digit one, U+00B9 ISOnum"
1021 ),
1022 ent!(186, "ordm", "masculine ordinal indicator, U+00BA ISOnum"),
1023 ent!(
1024 187,
1025 "raquo",
1026 "right-pointing double angle quotation mark right pointing guillemet, U+00BB ISOnum"
1027 ),
1028 ent!(
1029 188,
1030 "frac14",
1031 "vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum"
1032 ),
1033 ent!(
1034 189,
1035 "frac12",
1036 "vulgar fraction one half = fraction one half, U+00BD ISOnum"
1037 ),
1038 ent!(
1039 190,
1040 "frac34",
1041 "vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum"
1042 ),
1043 ent!(
1044 191,
1045 "iquest",
1046 "inverted question mark = turned question mark, U+00BF ISOnum"
1047 ),
1048 ent!(
1049 192,
1050 "Agrave",
1051 "latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1"
1052 ),
1053 ent!(
1054 193,
1055 "Aacute",
1056 "latin capital letter A with acute, U+00C1 ISOlat1"
1057 ),
1058 ent!(
1059 194,
1060 "Acirc",
1061 "latin capital letter A with circumflex, U+00C2 ISOlat1"
1062 ),
1063 ent!(
1064 195,
1065 "Atilde",
1066 "latin capital letter A with tilde, U+00C3 ISOlat1"
1067 ),
1068 ent!(
1069 196,
1070 "Auml",
1071 "latin capital letter A with diaeresis, U+00C4 ISOlat1"
1072 ),
1073 ent!(
1074 197,
1075 "Aring",
1076 "latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1"
1077 ),
1078 ent!(
1079 198,
1080 "AElig",
1081 "latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1"
1082 ),
1083 ent!(
1084 199,
1085 "Ccedil",
1086 "latin capital letter C with cedilla, U+00C7 ISOlat1"
1087 ),
1088 ent!(
1089 200,
1090 "Egrave",
1091 "latin capital letter E with grave, U+00C8 ISOlat1"
1092 ),
1093 ent!(
1094 201,
1095 "Eacute",
1096 "latin capital letter E with acute, U+00C9 ISOlat1"
1097 ),
1098 ent!(
1099 202,
1100 "Ecirc",
1101 "latin capital letter E with circumflex, U+00CA ISOlat1"
1102 ),
1103 ent!(
1104 203,
1105 "Euml",
1106 "latin capital letter E with diaeresis, U+00CB ISOlat1"
1107 ),
1108 ent!(
1109 204,
1110 "Igrave",
1111 "latin capital letter I with grave, U+00CC ISOlat1"
1112 ),
1113 ent!(
1114 205,
1115 "Iacute",
1116 "latin capital letter I with acute, U+00CD ISOlat1"
1117 ),
1118 ent!(
1119 206,
1120 "Icirc",
1121 "latin capital letter I with circumflex, U+00CE ISOlat1"
1122 ),
1123 ent!(
1124 207,
1125 "Iuml",
1126 "latin capital letter I with diaeresis, U+00CF ISOlat1"
1127 ),
1128 ent!(208, "ETH", "latin capital letter ETH, U+00D0 ISOlat1"),
1129 ent!(
1130 209,
1131 "Ntilde",
1132 "latin capital letter N with tilde, U+00D1 ISOlat1"
1133 ),
1134 ent!(
1135 210,
1136 "Ograve",
1137 "latin capital letter O with grave, U+00D2 ISOlat1"
1138 ),
1139 ent!(
1140 211,
1141 "Oacute",
1142 "latin capital letter O with acute, U+00D3 ISOlat1"
1143 ),
1144 ent!(
1145 212,
1146 "Ocirc",
1147 "latin capital letter O with circumflex, U+00D4 ISOlat1"
1148 ),
1149 ent!(
1150 213,
1151 "Otilde",
1152 "latin capital letter O with tilde, U+00D5 ISOlat1"
1153 ),
1154 ent!(
1155 214,
1156 "Ouml",
1157 "latin capital letter O with diaeresis, U+00D6 ISOlat1"
1158 ),
1159 ent!(215, "times", "multiplication sign, U+00D7 ISOnum"),
1160 ent!(
1161 216,
1162 "Oslash",
1163 "latin capital letter O with stroke latin capital letter O slash, U+00D8 ISOlat1"
1164 ),
1165 ent!(
1166 217,
1167 "Ugrave",
1168 "latin capital letter U with grave, U+00D9 ISOlat1"
1169 ),
1170 ent!(
1171 218,
1172 "Uacute",
1173 "latin capital letter U with acute, U+00DA ISOlat1"
1174 ),
1175 ent!(
1176 219,
1177 "Ucirc",
1178 "latin capital letter U with circumflex, U+00DB ISOlat1"
1179 ),
1180 ent!(
1181 220,
1182 "Uuml",
1183 "latin capital letter U with diaeresis, U+00DC ISOlat1"
1184 ),
1185 ent!(
1186 221,
1187 "Yacute",
1188 "latin capital letter Y with acute, U+00DD ISOlat1"
1189 ),
1190 ent!(222, "THORN", "latin capital letter THORN, U+00DE ISOlat1"),
1191 ent!(
1192 223,
1193 "szlig",
1194 "latin small letter sharp s = ess-zed, U+00DF ISOlat1"
1195 ),
1196 ent!(
1197 224,
1198 "agrave",
1199 "latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1"
1200 ),
1201 ent!(
1202 225,
1203 "aacute",
1204 "latin small letter a with acute, U+00E1 ISOlat1"
1205 ),
1206 ent!(
1207 226,
1208 "acirc",
1209 "latin small letter a with circumflex, U+00E2 ISOlat1"
1210 ),
1211 ent!(
1212 227,
1213 "atilde",
1214 "latin small letter a with tilde, U+00E3 ISOlat1"
1215 ),
1216 ent!(
1217 228,
1218 "auml",
1219 "latin small letter a with diaeresis, U+00E4 ISOlat1"
1220 ),
1221 ent!(
1222 229,
1223 "aring",
1224 "latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1"
1225 ),
1226 ent!(
1227 230,
1228 "aelig",
1229 "latin small letter ae = latin small ligature ae, U+00E6 ISOlat1"
1230 ),
1231 ent!(
1232 231,
1233 "ccedil",
1234 "latin small letter c with cedilla, U+00E7 ISOlat1"
1235 ),
1236 ent!(
1237 232,
1238 "egrave",
1239 "latin small letter e with grave, U+00E8 ISOlat1"
1240 ),
1241 ent!(
1242 233,
1243 "eacute",
1244 "latin small letter e with acute, U+00E9 ISOlat1"
1245 ),
1246 ent!(
1247 234,
1248 "ecirc",
1249 "latin small letter e with circumflex, U+00EA ISOlat1"
1250 ),
1251 ent!(
1252 235,
1253 "euml",
1254 "latin small letter e with diaeresis, U+00EB ISOlat1"
1255 ),
1256 ent!(
1257 236,
1258 "igrave",
1259 "latin small letter i with grave, U+00EC ISOlat1"
1260 ),
1261 ent!(
1262 237,
1263 "iacute",
1264 "latin small letter i with acute, U+00ED ISOlat1"
1265 ),
1266 ent!(
1267 238,
1268 "icirc",
1269 "latin small letter i with circumflex, U+00EE ISOlat1"
1270 ),
1271 ent!(
1272 239,
1273 "iuml",
1274 "latin small letter i with diaeresis, U+00EF ISOlat1"
1275 ),
1276 ent!(240, "eth", "latin small letter eth, U+00F0 ISOlat1"),
1277 ent!(
1278 241,
1279 "ntilde",
1280 "latin small letter n with tilde, U+00F1 ISOlat1"
1281 ),
1282 ent!(
1283 242,
1284 "ograve",
1285 "latin small letter o with grave, U+00F2 ISOlat1"
1286 ),
1287 ent!(
1288 243,
1289 "oacute",
1290 "latin small letter o with acute, U+00F3 ISOlat1"
1291 ),
1292 ent!(
1293 244,
1294 "ocirc",
1295 "latin small letter o with circumflex, U+00F4 ISOlat1"
1296 ),
1297 ent!(
1298 245,
1299 "otilde",
1300 "latin small letter o with tilde, U+00F5 ISOlat1"
1301 ),
1302 ent!(
1303 246,
1304 "ouml",
1305 "latin small letter o with diaeresis, U+00F6 ISOlat1"
1306 ),
1307 ent!(247, "divide", "division sign, U+00F7 ISOnum"),
1308 ent!(
1309 248,
1310 "oslash",
1311 "latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1"
1312 ),
1313 ent!(
1314 249,
1315 "ugrave",
1316 "latin small letter u with grave, U+00F9 ISOlat1"
1317 ),
1318 ent!(
1319 250,
1320 "uacute",
1321 "latin small letter u with acute, U+00FA ISOlat1"
1322 ),
1323 ent!(
1324 251,
1325 "ucirc",
1326 "latin small letter u with circumflex, U+00FB ISOlat1"
1327 ),
1328 ent!(
1329 252,
1330 "uuml",
1331 "latin small letter u with diaeresis, U+00FC ISOlat1"
1332 ),
1333 ent!(
1334 253,
1335 "yacute",
1336 "latin small letter y with acute, U+00FD ISOlat1"
1337 ),
1338 ent!(
1339 254,
1340 "thorn",
1341 "latin small letter thorn with, U+00FE ISOlat1"
1342 ),
1343 ent!(
1344 255,
1345 "yuml",
1346 "latin small letter y with diaeresis, U+00FF ISOlat1"
1347 ),
1348 ent!(338, "OElig", "latin capital ligature OE, U+0152 ISOlat2"),
1349 ent!(339, "oelig", "latin small ligature oe, U+0153 ISOlat2"),
1350 ent!(
1351 352,
1352 "Scaron",
1353 "latin capital letter S with caron, U+0160 ISOlat2"
1354 ),
1355 ent!(
1356 353,
1357 "scaron",
1358 "latin small letter s with caron, U+0161 ISOlat2"
1359 ),
1360 ent!(
1361 376,
1362 "Yuml",
1363 "latin capital letter Y with diaeresis, U+0178 ISOlat2"
1364 ),
1365 ent!(
1366 402,
1367 "fnof",
1368 "latin small f with hook = function = florin, U+0192 ISOtech"
1369 ),
1370 ent!(
1371 710,
1372 "circ",
1373 "modifier letter circumflex accent, U+02C6 ISOpub"
1374 ),
1375 ent!(732, "tilde", "small tilde, U+02DC ISOdia"),
1376 ent!(913, "Alpha", "greek capital letter alpha, U+0391"),
1377 ent!(914, "Beta", "greek capital letter beta, U+0392"),
1378 ent!(915, "Gamma", "greek capital letter gamma, U+0393 ISOgrk3"),
1379 ent!(916, "Delta", "greek capital letter delta, U+0394 ISOgrk3"),
1380 ent!(917, "Epsilon", "greek capital letter epsilon, U+0395"),
1381 ent!(918, "Zeta", "greek capital letter zeta, U+0396"),
1382 ent!(919, "Eta", "greek capital letter eta, U+0397"),
1383 ent!(920, "Theta", "greek capital letter theta, U+0398 ISOgrk3"),
1384 ent!(921, "Iota", "greek capital letter iota, U+0399"),
1385 ent!(922, "Kappa", "greek capital letter kappa, U+039A"),
1386 ent!(923, "Lambda", "greek capital letter lambda, U+039B ISOgrk3"),
1387 ent!(924, "Mu", "greek capital letter mu, U+039C"),
1388 ent!(925, "Nu", "greek capital letter nu, U+039D"),
1389 ent!(926, "Xi", "greek capital letter xi, U+039E ISOgrk3"),
1390 ent!(927, "Omicron", "greek capital letter omicron, U+039F"),
1391 ent!(928, "Pi", "greek capital letter pi, U+03A0 ISOgrk3"),
1392 ent!(929, "Rho", "greek capital letter rho, U+03A1"),
1393 ent!(931, "Sigma", "greek capital letter sigma, U+03A3 ISOgrk3"),
1394 ent!(932, "Tau", "greek capital letter tau, U+03A4"),
1395 ent!(
1396 933,
1397 "Upsilon",
1398 "greek capital letter upsilon, U+03A5 ISOgrk3"
1399 ),
1400 ent!(934, "Phi", "greek capital letter phi, U+03A6 ISOgrk3"),
1401 ent!(935, "Chi", "greek capital letter chi, U+03A7"),
1402 ent!(936, "Psi", "greek capital letter psi, U+03A8 ISOgrk3"),
1403 ent!(937, "Omega", "greek capital letter omega, U+03A9 ISOgrk3"),
1404 ent!(945, "alpha", "greek small letter alpha, U+03B1 ISOgrk3"),
1405 ent!(946, "beta", "greek small letter beta, U+03B2 ISOgrk3"),
1406 ent!(947, "gamma", "greek small letter gamma, U+03B3 ISOgrk3"),
1407 ent!(948, "delta", "greek small letter delta, U+03B4 ISOgrk3"),
1408 ent!(949, "epsilon", "greek small letter epsilon, U+03B5 ISOgrk3"),
1409 ent!(950, "zeta", "greek small letter zeta, U+03B6 ISOgrk3"),
1410 ent!(951, "eta", "greek small letter eta, U+03B7 ISOgrk3"),
1411 ent!(952, "theta", "greek small letter theta, U+03B8 ISOgrk3"),
1412 ent!(953, "iota", "greek small letter iota, U+03B9 ISOgrk3"),
1413 ent!(954, "kappa", "greek small letter kappa, U+03BA ISOgrk3"),
1414 ent!(955, "lambda", "greek small letter lambda, U+03BB ISOgrk3"),
1415 ent!(956, "mu", "greek small letter mu, U+03BC ISOgrk3"),
1416 ent!(957, "nu", "greek small letter nu, U+03BD ISOgrk3"),
1417 ent!(958, "xi", "greek small letter xi, U+03BE ISOgrk3"),
1418 ent!(959, "omicron", "greek small letter omicron, U+03BF NEW"),
1419 ent!(960, "pi", "greek small letter pi, U+03C0 ISOgrk3"),
1420 ent!(961, "rho", "greek small letter rho, U+03C1 ISOgrk3"),
1421 ent!(
1422 962,
1423 "sigmaf",
1424 "greek small letter final sigma, U+03C2 ISOgrk3"
1425 ),
1426 ent!(963, "sigma", "greek small letter sigma, U+03C3 ISOgrk3"),
1427 ent!(964, "tau", "greek small letter tau, U+03C4 ISOgrk3"),
1428 ent!(965, "upsilon", "greek small letter upsilon, U+03C5 ISOgrk3"),
1429 ent!(966, "phi", "greek small letter phi, U+03C6 ISOgrk3"),
1430 ent!(967, "chi", "greek small letter chi, U+03C7 ISOgrk3"),
1431 ent!(968, "psi", "greek small letter psi, U+03C8 ISOgrk3"),
1432 ent!(969, "omega", "greek small letter omega, U+03C9 ISOgrk3"),
1433 ent!(
1434 977,
1435 "thetasym",
1436 "greek small letter theta symbol, U+03D1 NEW"
1437 ),
1438 ent!(978, "upsih", "greek upsilon with hook symbol, U+03D2 NEW"),
1439 ent!(982, "piv", "greek pi symbol, U+03D6 ISOgrk3"),
1440 ent!(8194, "ensp", "en space, U+2002 ISOpub"),
1441 ent!(8195, "emsp", "em space, U+2003 ISOpub"),
1442 ent!(8201, "thinsp", "thin space, U+2009 ISOpub"),
1443 ent!(8204, "zwnj", "zero width non-joiner, U+200C NEW RFC 2070"),
1444 ent!(8205, "zwj", "zero width joiner, U+200D NEW RFC 2070"),
1445 ent!(8206, "lrm", "left-to-right mark, U+200E NEW RFC 2070"),
1446 ent!(8207, "rlm", "right-to-left mark, U+200F NEW RFC 2070"),
1447 ent!(8211, "ndash", "en dash, U+2013 ISOpub"),
1448 ent!(8212, "mdash", "em dash, U+2014 ISOpub"),
1449 ent!(8216, "lsquo", "left single quotation mark, U+2018 ISOnum"),
1450 ent!(8217, "rsquo", "right single quotation mark, U+2019 ISOnum"),
1451 ent!(8218, "sbquo", "single low-9 quotation mark, U+201A NEW"),
1452 ent!(8220, "ldquo", "left double quotation mark, U+201C ISOnum"),
1453 ent!(8221, "rdquo", "right double quotation mark, U+201D ISOnum"),
1454 ent!(8222, "bdquo", "double low-9 quotation mark, U+201E NEW"),
1455 ent!(8224, "dagger", "dagger, U+2020 ISOpub"),
1456 ent!(8225, "Dagger", "double dagger, U+2021 ISOpub"),
1457 ent!(8226, "bull", "bullet = black small circle, U+2022 ISOpub"),
1458 ent!(
1459 8230,
1460 "hellip",
1461 "horizontal ellipsis = three dot leader, U+2026 ISOpub"
1462 ),
1463 ent!(8240, "permil", "per mille sign, U+2030 ISOtech"),
1464 ent!(8242, "prime", "prime = minutes = feet, U+2032 ISOtech"),
1465 ent!(
1466 8243,
1467 "Prime",
1468 "double prime = seconds = inches, U+2033 ISOtech"
1469 ),
1470 ent!(
1471 8249,
1472 "lsaquo",
1473 "single left-pointing angle quotation mark, U+2039 ISO proposed"
1474 ),
1475 ent!(
1476 8250,
1477 "rsaquo",
1478 "single right-pointing angle quotation mark, U+203A ISO proposed"
1479 ),
1480 ent!(8254, "oline", "overline = spacing overscore, U+203E NEW"),
1481 ent!(8260, "frasl", "fraction slash, U+2044 NEW"),
1482 ent!(8364, "euro", "euro sign, U+20AC NEW"),
1483 ent!(
1484 8465,
1485 "image",
1486 "blackletter capital I = imaginary part, U+2111 ISOamso"
1487 ),
1488 ent!(
1489 8472,
1490 "weierp",
1491 "script capital P = power set = Weierstrass p, U+2118 ISOamso"
1492 ),
1493 ent!(
1494 8476,
1495 "real",
1496 "blackletter capital R = real part symbol, U+211C ISOamso"
1497 ),
1498 ent!(8482, "trade", "trade mark sign, U+2122 ISOnum"),
1499 ent!(
1500 8501,
1501 "alefsym",
1502 "alef symbol = first transfinite cardinal, U+2135 NEW"
1503 ),
1504 ent!(8592, "larr", "leftwards arrow, U+2190 ISOnum"),
1505 ent!(8593, "uarr", "upwards arrow, U+2191 ISOnum"),
1506 ent!(8594, "rarr", "rightwards arrow, U+2192 ISOnum"),
1507 ent!(8595, "darr", "downwards arrow, U+2193 ISOnum"),
1508 ent!(8596, "harr", "left right arrow, U+2194 ISOamsa"),
1509 ent!(
1510 8629,
1511 "crarr",
1512 "downwards arrow with corner leftwards = carriage return, U+21B5 NEW"
1513 ),
1514 ent!(8656, "lArr", "leftwards double arrow, U+21D0 ISOtech"),
1515 ent!(8657, "uArr", "upwards double arrow, U+21D1 ISOamsa"),
1516 ent!(8658, "rArr", "rightwards double arrow, U+21D2 ISOtech"),
1517 ent!(8659, "dArr", "downwards double arrow, U+21D3 ISOamsa"),
1518 ent!(8660, "hArr", "left right double arrow, U+21D4 ISOamsa"),
1519 ent!(8704, "forall", "for all, U+2200 ISOtech"),
1520 ent!(8706, "part", "partial differential, U+2202 ISOtech"),
1521 ent!(8707, "exist", "there exists, U+2203 ISOtech"),
1522 ent!(
1523 8709,
1524 "empty",
1525 "empty set = null set = diameter, U+2205 ISOamso"
1526 ),
1527 ent!(8711, "nabla", "nabla = backward difference, U+2207 ISOtech"),
1528 ent!(8712, "isin", "element of, U+2208 ISOtech"),
1529 ent!(8713, "notin", "not an element of, U+2209 ISOtech"),
1530 ent!(8715, "ni", "contains as member, U+220B ISOtech"),
1531 ent!(8719, "prod", "n-ary product = product sign, U+220F ISOamsb"),
1532 ent!(8721, "sum", "n-ary summation, U+2211 ISOamsb"),
1533 ent!(8722, "minus", "minus sign, U+2212 ISOtech"),
1534 ent!(8727, "lowast", "asterisk operator, U+2217 ISOtech"),
1535 ent!(8730, "radic", "square root = radical sign, U+221A ISOtech"),
1536 ent!(8733, "prop", "proportional to, U+221D ISOtech"),
1537 ent!(8734, "infin", "infinity, U+221E ISOtech"),
1538 ent!(8736, "ang", "angle, U+2220 ISOamso"),
1539 ent!(8743, "and", "logical and = wedge, U+2227 ISOtech"),
1540 ent!(8744, "or", "logical or = vee, U+2228 ISOtech"),
1541 ent!(8745, "cap", "intersection = cap, U+2229 ISOtech"),
1542 ent!(8746, "cup", "union = cup, U+222A ISOtech"),
1543 ent!(8747, "int", "integral, U+222B ISOtech"),
1544 ent!(8756, "there4", "therefore, U+2234 ISOtech"),
1545 ent!(
1546 8764,
1547 "sim",
1548 "tilde operator = varies with = similar to, U+223C ISOtech"
1549 ),
1550 ent!(8773, "cong", "approximately equal to, U+2245 ISOtech"),
1551 ent!(
1552 8776,
1553 "asymp",
1554 "almost equal to = asymptotic to, U+2248 ISOamsr"
1555 ),
1556 ent!(8800, "ne", "not equal to, U+2260 ISOtech"),
1557 ent!(8801, "equiv", "identical to, U+2261 ISOtech"),
1558 ent!(8804, "le", "less-than or equal to, U+2264 ISOtech"),
1559 ent!(8805, "ge", "greater-than or equal to, U+2265 ISOtech"),
1560 ent!(8834, "sub", "subset of, U+2282 ISOtech"),
1561 ent!(8835, "sup", "superset of, U+2283 ISOtech"),
1562 ent!(8836, "nsub", "not a subset of, U+2284 ISOamsn"),
1563 ent!(8838, "sube", "subset of or equal to, U+2286 ISOtech"),
1564 ent!(8839, "supe", "superset of or equal to, U+2287 ISOtech"),
1565 ent!(8853, "oplus", "circled plus = direct sum, U+2295 ISOamsb"),
1566 ent!(
1567 8855,
1568 "otimes",
1569 "circled times = vector product, U+2297 ISOamsb"
1570 ),
1571 ent!(
1572 8869,
1573 "perp",
1574 "up tack = orthogonal to = perpendicular, U+22A5 ISOtech"
1575 ),
1576 ent!(8901, "sdot", "dot operator, U+22C5 ISOamsb"),
1577 ent!(8968, "lceil", "left ceiling = apl upstile, U+2308 ISOamsc"),
1578 ent!(8969, "rceil", "right ceiling, U+2309 ISOamsc"),
1579 ent!(8970, "lfloor", "left floor = apl downstile, U+230A ISOamsc"),
1580 ent!(8971, "rfloor", "right floor, U+230B ISOamsc"),
1581 ent!(
1582 9001,
1583 "lang",
1584 "left-pointing angle bracket = bra, U+2329 ISOtech"
1585 ),
1586 ent!(
1587 9002,
1588 "rang",
1589 "right-pointing angle bracket = ket, U+232A ISOtech"
1590 ),
1591 ent!(9674, "loz", "lozenge, U+25CA ISOpub"),
1592 ent!(9824, "spades", "black spade suit, U+2660 ISOpub"),
1593 ent!(9827, "clubs", "black club suit = shamrock, U+2663 ISOpub"),
1594 ent!(
1595 9829,
1596 "hearts",
1597 "black heart suit = valentine, U+2665 ISOpub"
1598 ),
1599 ent!(9830, "diams", "black diamond suit, U+2666 ISOpub"),
1600];
1601
1602#[no_mangle]
1613pub unsafe extern "C" fn htmlEntityLookup(name: *const xmlChar) -> *const _htmlEntityDesc {
1614 if name.is_null() {
1615 return ptr::null();
1616 }
1617 let bytes = unsafe { xmlstr_to_bytes(name) };
1618 for e in HTML40_ENTITIES {
1619 let ename = unsafe { core::ffi::CStr::from_ptr(e.name) }.to_bytes();
1620 if bytes == ename {
1621 return e as *const _htmlEntityDesc;
1622 }
1623 }
1624 ptr::null()
1625}
1626
1627#[no_mangle]
1638pub unsafe extern "C" fn htmlEntityValueLookup(value: c_uint) -> *const _htmlEntityDesc {
1639 for e in HTML40_ENTITIES {
1640 if e.value == value {
1641 return e as *const _htmlEntityDesc;
1642 }
1643 }
1644 ptr::null()
1645}
1646
1647#[inline]
1650unsafe fn html_entity_value_lookup_static(value: c_uint) -> *const _htmlEntityDesc {
1651 for e in HTML40_ENTITIES {
1652 if e.value == value {
1653 return e as *const _htmlEntityDesc;
1654 }
1655 }
1656 ptr::null()
1657}
1658
1659static HTML_START_CLOSE: &[(&str, &str)] = &[
1667 ("a", "a"),
1668 ("a", "fieldset"),
1669 ("a", "table"),
1670 ("a", "td"),
1671 ("a", "th"),
1672 ("address", "dd"),
1673 ("address", "dl"),
1674 ("address", "dt"),
1675 ("address", "form"),
1676 ("address", "li"),
1677 ("address", "ul"),
1678 ("b", "center"),
1679 ("b", "p"),
1680 ("b", "td"),
1681 ("b", "th"),
1682 ("big", "p"),
1683 ("caption", "col"),
1684 ("caption", "colgroup"),
1685 ("caption", "tbody"),
1686 ("caption", "tfoot"),
1687 ("caption", "thead"),
1688 ("caption", "tr"),
1689 ("col", "col"),
1690 ("col", "colgroup"),
1691 ("col", "tbody"),
1692 ("col", "tfoot"),
1693 ("col", "thead"),
1694 ("col", "tr"),
1695 ("colgroup", "colgroup"),
1696 ("colgroup", "tbody"),
1697 ("colgroup", "tfoot"),
1698 ("colgroup", "thead"),
1699 ("colgroup", "tr"),
1700 ("dd", "dt"),
1701 ("dir", "dd"),
1702 ("dir", "dl"),
1703 ("dir", "dt"),
1704 ("dir", "form"),
1705 ("dir", "ul"),
1706 ("dl", "form"),
1707 ("dl", "li"),
1708 ("dt", "dd"),
1709 ("dt", "dl"),
1710 ("font", "center"),
1711 ("font", "td"),
1712 ("font", "th"),
1713 ("form", "form"),
1714 ("h1", "fieldset"),
1715 ("h1", "form"),
1716 ("h1", "li"),
1717 ("h1", "p"),
1718 ("h1", "table"),
1719 ("h2", "fieldset"),
1720 ("h2", "form"),
1721 ("h2", "li"),
1722 ("h2", "p"),
1723 ("h2", "table"),
1724 ("h3", "fieldset"),
1725 ("h3", "form"),
1726 ("h3", "li"),
1727 ("h3", "p"),
1728 ("h3", "table"),
1729 ("h4", "fieldset"),
1730 ("h4", "form"),
1731 ("h4", "li"),
1732 ("h4", "p"),
1733 ("h4", "table"),
1734 ("h5", "fieldset"),
1735 ("h5", "form"),
1736 ("h5", "li"),
1737 ("h5", "p"),
1738 ("h5", "table"),
1739 ("h6", "fieldset"),
1740 ("h6", "form"),
1741 ("h6", "li"),
1742 ("h6", "p"),
1743 ("h6", "table"),
1744 ("head", "a"),
1745 ("head", "abbr"),
1746 ("head", "acronym"),
1747 ("head", "address"),
1748 ("head", "b"),
1749 ("head", "bdo"),
1750 ("head", "big"),
1751 ("head", "blockquote"),
1752 ("head", "body"),
1753 ("head", "br"),
1754 ("head", "center"),
1755 ("head", "cite"),
1756 ("head", "code"),
1757 ("head", "dd"),
1758 ("head", "dfn"),
1759 ("head", "dir"),
1760 ("head", "div"),
1761 ("head", "dl"),
1762 ("head", "dt"),
1763 ("head", "em"),
1764 ("head", "fieldset"),
1765 ("head", "font"),
1766 ("head", "form"),
1767 ("head", "frameset"),
1768 ("head", "h1"),
1769 ("head", "h2"),
1770 ("head", "h3"),
1771 ("head", "h4"),
1772 ("head", "h5"),
1773 ("head", "h6"),
1774 ("head", "hr"),
1775 ("head", "i"),
1776 ("head", "iframe"),
1777 ("head", "img"),
1778 ("head", "kbd"),
1779 ("head", "li"),
1780 ("head", "listing"),
1781 ("head", "map"),
1782 ("head", "menu"),
1783 ("head", "ol"),
1784 ("head", "p"),
1785 ("head", "pre"),
1786 ("head", "q"),
1787 ("head", "s"),
1788 ("head", "samp"),
1789 ("head", "small"),
1790 ("head", "span"),
1791 ("head", "strike"),
1792 ("head", "strong"),
1793 ("head", "sub"),
1794 ("head", "sup"),
1795 ("head", "table"),
1796 ("head", "tt"),
1797 ("head", "u"),
1798 ("head", "ul"),
1799 ("head", "var"),
1800 ("head", "xmp"),
1801 ("hr", "form"),
1802 ("i", "center"),
1803 ("i", "p"),
1804 ("i", "td"),
1805 ("i", "th"),
1806 ("legend", "fieldset"),
1807 ("li", "li"),
1808 ("link", "body"),
1809 ("link", "frameset"),
1810 ("listing", "dd"),
1811 ("listing", "dl"),
1812 ("listing", "dt"),
1813 ("listing", "fieldset"),
1814 ("listing", "form"),
1815 ("listing", "li"),
1816 ("listing", "table"),
1817 ("listing", "ul"),
1818 ("menu", "dd"),
1819 ("menu", "dl"),
1820 ("menu", "dt"),
1821 ("menu", "form"),
1822 ("menu", "ul"),
1823 ("ol", "form"),
1824 ("option", "optgroup"),
1825 ("option", "option"),
1826 ("p", "address"),
1827 ("p", "blockquote"),
1828 ("p", "body"),
1829 ("p", "caption"),
1830 ("p", "center"),
1831 ("p", "col"),
1832 ("p", "colgroup"),
1833 ("p", "dd"),
1834 ("p", "dir"),
1835 ("p", "div"),
1836 ("p", "dl"),
1837 ("p", "dt"),
1838 ("p", "fieldset"),
1839 ("p", "form"),
1840 ("p", "frameset"),
1841 ("p", "h1"),
1842 ("p", "h2"),
1843 ("p", "h3"),
1844 ("p", "h4"),
1845 ("p", "h5"),
1846 ("p", "h6"),
1847 ("p", "head"),
1848 ("p", "hr"),
1849 ("p", "li"),
1850 ("p", "listing"),
1851 ("p", "menu"),
1852 ("p", "ol"),
1853 ("p", "p"),
1854 ("p", "pre"),
1855 ("p", "table"),
1856 ("p", "tbody"),
1857 ("p", "td"),
1858 ("p", "tfoot"),
1859 ("p", "th"),
1860 ("p", "title"),
1861 ("p", "tr"),
1862 ("p", "ul"),
1863 ("p", "xmp"),
1864 ("pre", "dd"),
1865 ("pre", "dl"),
1866 ("pre", "dt"),
1867 ("pre", "fieldset"),
1868 ("pre", "form"),
1869 ("pre", "li"),
1870 ("pre", "table"),
1871 ("pre", "ul"),
1872 ("s", "p"),
1873 ("script", "noscript"),
1874 ("small", "p"),
1875 ("span", "td"),
1876 ("span", "th"),
1877 ("strike", "p"),
1878 ("style", "body"),
1879 ("style", "frameset"),
1880 ("tbody", "tbody"),
1881 ("tbody", "tfoot"),
1882 ("td", "tbody"),
1883 ("td", "td"),
1884 ("td", "tfoot"),
1885 ("td", "th"),
1886 ("td", "tr"),
1887 ("tfoot", "tbody"),
1888 ("th", "tbody"),
1889 ("th", "td"),
1890 ("th", "tfoot"),
1891 ("th", "th"),
1892 ("th", "tr"),
1893 ("thead", "tbody"),
1894 ("thead", "tfoot"),
1895 ("title", "body"),
1896 ("title", "frameset"),
1897 ("tr", "tbody"),
1898 ("tr", "tfoot"),
1899 ("tr", "tr"),
1900 ("tt", "p"),
1901 ("u", "p"),
1902 ("u", "td"),
1903 ("u", "th"),
1904 ("ul", "address"),
1905 ("ul", "form"),
1906 ("ul", "menu"),
1907 ("ul", "pre"),
1908 ("xmp", "dd"),
1909 ("xmp", "dl"),
1910 ("xmp", "dt"),
1911 ("xmp", "fieldset"),
1912 ("xmp", "form"),
1913 ("xmp", "li"),
1914 ("xmp", "table"),
1915 ("xmp", "ul"),
1916];
1917
1918unsafe fn html_check_auto_close(newtag: *const xmlChar, oldtag: *const xmlChar) -> bool {
1922 if newtag.is_null() || oldtag.is_null() {
1923 return false;
1924 }
1925 let new_bytes = unsafe { xmlstr_to_bytes(newtag) };
1926 let old_bytes = unsafe { xmlstr_to_bytes(oldtag) };
1927 HTML_START_CLOSE
1928 .iter()
1929 .any(|(old, new)| old.as_bytes() == old_bytes && new.as_bytes() == new_bytes)
1930}
1931
1932#[no_mangle]
1942pub unsafe extern "C" fn htmlAutoCloseTag(
1943 _doc: *mut _xmlDoc,
1944 name: *const xmlChar,
1945 elem: *mut _xmlNode,
1946) -> c_int {
1947 if elem.is_null() {
1948 return 1;
1949 }
1950 let n = unsafe { &*elem };
1951 if n.name.is_null() {
1952 } else if unsafe { xml_strcmp(name, n.name) } == 0 {
1955 return 0;
1956 }
1957 if unsafe { html_check_auto_close(n.name, name) } {
1958 return 1;
1959 }
1960 let mut child = n.children;
1961 while !child.is_null() {
1962 if unsafe { htmlAutoCloseTag(_doc, name, child) } != 0 {
1963 return 1;
1964 }
1965 child = unsafe { (*child).next };
1966 }
1967 0
1968}
1969
1970#[no_mangle]
1979pub unsafe extern "C" fn htmlIsAutoClosed(doc: *mut _xmlDoc, elem: *mut _xmlNode) -> c_int {
1980 if elem.is_null() {
1981 return 1;
1982 }
1983 let n = unsafe { &*elem };
1984 let mut child = n.children;
1985 while !child.is_null() {
1986 if unsafe { htmlAutoCloseTag(doc, n.name, child) } != 0 {
1987 return 1;
1988 }
1989 child = unsafe { (*child).next };
1990 }
1991 0
1992}
1993
1994static HTML_SCRIPT_ATTRIBUTES: &[&str] = &[
1997 "onclick",
1998 "ondblclick",
1999 "onmousedown",
2000 "onmouseup",
2001 "onmouseover",
2002 "onmousemove",
2003 "onmouseout",
2004 "onkeypress",
2005 "onkeydown",
2006 "onkeyup",
2007 "onload",
2008 "onunload",
2009 "onfocus",
2010 "onblur",
2011 "onsubmit",
2012 "onreset",
2013 "onchange",
2014 "onselect",
2015];
2016
2017#[no_mangle]
2026pub unsafe extern "C" fn htmlIsScriptAttribute(name: *const xmlChar) -> c_int {
2027 if name.is_null() {
2028 return 0;
2029 }
2030 let bytes = unsafe { xmlstr_to_bytes(name) };
2031 if bytes.len() < 3 || bytes[0] != b'o' || bytes[1] != b'n' {
2032 return 0;
2033 }
2034 for cand in HTML_SCRIPT_ATTRIBUTES {
2035 if bytes == cand.as_bytes() {
2036 return 1;
2037 }
2038 }
2039 0
2040}
2041
2042#[no_mangle]
2054pub const unsafe extern "C" fn htmlElementAllowedHere(
2055 _parent: *const _htmlElemDesc,
2056 _elt: *const xmlChar,
2057) -> c_int {
2058 1
2059}
2060
2061#[no_mangle]
2069pub const unsafe extern "C" fn htmlElementStatusHere(
2070 _parent: *const _htmlElemDesc,
2071 _elt: *const _htmlElemDesc,
2072) -> c_int {
2073 HTML_VALID
2074}
2075
2076#[no_mangle]
2084pub const unsafe extern "C" fn htmlAttrAllowed(
2085 _elt: *const _htmlElemDesc,
2086 _attr: *const xmlChar,
2087 _legacy: c_int,
2088) -> c_int {
2089 HTML_VALID
2090}
2091
2092#[no_mangle]
2100pub const unsafe extern "C" fn htmlNodeStatus(_node: *mut _xmlNode, _legacy: c_int) -> c_int {
2101 HTML_VALID
2102}
2103
2104#[no_mangle]
2123pub unsafe extern "C" fn htmlEncodeEntities(
2124 out: *mut u8,
2125 outlen: *mut c_int,
2126 input: *const u8,
2127 inlen: *mut c_int,
2128 quoteChar: c_int,
2129) -> c_int {
2130 if out.is_null() || outlen.is_null() || inlen.is_null() || input.is_null() {
2131 return -1;
2132 }
2133 let outend = (out as usize).wrapping_add((*outlen).max(0) as usize);
2134 let inend = (input as usize).wrapping_add((*inlen).max(0) as usize);
2135 let mut in_ptr = input as usize;
2136 let mut out_ptr = out as usize;
2137 let mut processed = in_ptr;
2138
2139 while in_ptr < inend {
2140 let mut c: c_uint;
2141
2142 let mut trailing: c_int;
2143
2144 let d: c_uint = unsafe { *(in_ptr as *const u8) as c_uint };
2145 in_ptr += 1;
2146 if d < 0x80 {
2147 c = d;
2148 trailing = 0;
2149 } else if d < 0xC0 {
2150 *outlen = (out_ptr - out as usize) as c_int;
2152 *inlen = (processed - input as usize) as c_int;
2153 return -2;
2154 } else if d < 0xE0 {
2155 c = d & 0x1F;
2156 trailing = 1;
2157 } else if d < 0xF0 {
2158 c = d & 0x0F;
2159 trailing = 2;
2160 } else if d < 0xF8 {
2161 c = d & 0x07;
2162 trailing = 3;
2163 } else {
2164 *outlen = (out_ptr - out as usize) as c_int;
2166 *inlen = (processed - input as usize) as c_int;
2167 return -2;
2168 }
2169
2170 if inend - in_ptr < trailing as usize {
2171 break;
2172 }
2173
2174 while trailing > 0 {
2175 let t = unsafe { *(in_ptr as *const u8) as c_uint };
2176 in_ptr += 1;
2177 if (t & 0xC0) != 0x80 {
2178 *outlen = (out_ptr - out as usize) as c_int;
2179 *inlen = (processed - input as usize) as c_int;
2180 return -2;
2181 }
2182 c = (c << 6) | (t & 0x3F);
2183 trailing -= 1;
2184 }
2185
2186 if (c < 0x80)
2188 && (c != quoteChar as c_uint)
2189 && (c != b'&' as c_uint)
2190 && (c != b'<' as c_uint)
2191 && (c != b'>' as c_uint)
2192 {
2193 if out_ptr >= outend {
2194 break;
2195 }
2196 unsafe { *(out_ptr as *mut u8) = c as u8 };
2197 out_ptr += 1;
2198 } else {
2199 let ent = unsafe { html_entity_value_lookup_static(c) };
2200 let mut nbuf = [0u8; 16];
2201 let (cp, len): (*const u8, usize) = if ent.is_null() {
2202 nbuf[0] = b'#';
2204 let mut i = 1usize;
2205 let mut digits = [0u8; 10];
2206 let mut nd = 0usize;
2207 let mut v = c;
2208 if v == 0 {
2209 digits[0] = b'0';
2210 nd = 1;
2211 }
2212 while v > 0 {
2213 digits[nd] = b'0' + (v % 10) as u8;
2214 nd += 1;
2215 v /= 10;
2216 }
2217 while nd > 0 {
2218 nd -= 1;
2219 nbuf[i] = digits[nd];
2220 i += 1;
2221 }
2222 (nbuf.as_ptr(), i)
2223 } else {
2224 (unsafe { (*ent).name } as *const u8, unsafe {
2225 xml_strlen((*ent).name as *const xmlChar)
2226 })
2227 };
2228 if outend - out_ptr < len + 2 {
2229 break;
2230 }
2231 unsafe {
2232 *(out_ptr as *mut u8) = b'&';
2233 ptr::copy_nonoverlapping(cp, (out_ptr + 1) as *mut u8, len);
2234 *((out_ptr + 1 + len) as *mut u8) = b';';
2235 }
2236 out_ptr += len + 2;
2237 }
2238 processed = in_ptr;
2239 }
2240
2241 *outlen = (out_ptr - out as usize) as c_int;
2242 *inlen = (processed - input as usize) as c_int;
2243 0
2244}
2245
2246#[no_mangle]
2259pub unsafe extern "C" fn htmlDecodeEntities(
2260 _ctxt: *mut c_void,
2261 _len: c_int,
2262 _end: xmlChar,
2263 _end2: xmlChar,
2264 _end3: xmlChar,
2265) -> *mut xmlChar {
2266 static DEPRECATED: AtomicBool = AtomicBool::new(false);
2267 if !DEPRECATED.swap(true, Ordering::Relaxed) {
2268 let msg = b"htmlDecodeEntities() deprecated function reached\n";
2270 unsafe {
2271 libc::fwrite(
2272 msg.as_ptr() as *const c_void,
2273 1,
2274 msg.len(),
2275 libc::fdopen(2, b"w\0" as *const u8 as *const c_char),
2276 );
2277 }
2278 }
2279 ptr::null_mut()
2280}
2281
2282#[no_mangle]
2292pub unsafe extern "C" fn htmlIsBooleanAttr(name: *const xmlChar) -> c_int {
2293 if name.is_null() {
2294 return 0;
2295 }
2296 let b = unsafe { xmlstr_to_bytes(name) };
2297 if b.is_empty() {
2298 return 0;
2299 }
2300 let mut i = 0usize;
2301 let mut suffix: Option<&'static [u8]> = None;
2302 match b[i].to_ascii_lowercase() {
2303 b'c' => {
2304 i += 1;
2305 match b.get(i).map(|&x| x.to_ascii_lowercase()) {
2306 Some(b'h') => suffix = Some(b"ecked"),
2307 Some(b'o') => suffix = Some(b"mpact"),
2308 _ => {}
2309 }
2310 }
2311 b'd' => {
2312 i += 1;
2313 match b.get(i).map(|&x| x.to_ascii_lowercase()) {
2314 Some(b'e') => {
2315 i += 1;
2316 match b.get(i).map(|&x| x.to_ascii_lowercase()) {
2317 Some(b'c') => suffix = Some(b"lare"),
2318 Some(b'f') => suffix = Some(b"er"),
2319 _ => {}
2320 }
2321 }
2322 Some(b'i') => suffix = Some(b"sabled"),
2323 _ => {}
2324 }
2325 }
2326 b'i' => suffix = Some(b"smap"),
2327 b'm' => suffix = Some(b"ultiple"),
2328 b'n' => {
2329 i += 1;
2330 if b.get(i).map(|&x| x.to_ascii_lowercase()) == Some(b'o') {
2331 i += 1;
2332 match b.get(i).map(|&x| x.to_ascii_lowercase()) {
2333 Some(b'h') => suffix = Some(b"ref"),
2334 Some(b'r') => suffix = Some(b"esize"),
2335 Some(b's') => suffix = Some(b"hade"),
2336 Some(b'w') => suffix = Some(b"rap"),
2337 _ => {}
2338 }
2339 }
2340 }
2341 b'r' => suffix = Some(b"eadonly"),
2342 b's' => suffix = Some(b"elected"),
2343 _ => {}
2344 }
2345 let Some(suffix) = suffix else {
2346 return 0;
2347 };
2348 if b.len() == i + 1 + suffix.len() && b[i + 1..].eq_ignore_ascii_case(suffix) {
2349 1
2350 } else {
2351 0
2352 }
2353}
2354
2355static HTML_OMITTED_DEFAULT_VALUE: AtomicI32 = AtomicI32::new(1);
2362
2363#[no_mangle]
2371pub unsafe extern "C" fn htmlHandleOmittedElem(val: c_int) -> c_int {
2372 HTML_OMITTED_DEFAULT_VALUE.swap(val, Ordering::Relaxed)
2373}
2374
2375#[no_mangle]
2383pub const unsafe extern "C" fn htmlInitAutoClose() {
2384 }
2386
2387#[no_mangle]
2398pub const unsafe extern "C" fn htmlDefaultSAXHandlerInit() {
2399 }
2401
2402#[no_mangle]
2414pub const unsafe extern "C" fn htmlParseEntityRef(
2415 _ctxt: *mut c_void,
2416 _str: *mut *const xmlChar,
2417) -> *const _htmlEntityDesc {
2418 ptr::null()
2419}
2420
2421#[no_mangle]
2429pub const unsafe extern "C" fn htmlParseCharRef(_ctxt: *mut c_void) -> c_int {
2430 0
2431}
2432
2433#[allow(dead_code)]
2451struct HtmlOpaqueCtxt {
2452 doc: *mut _xmlDoc,
2454 current: *mut _xmlNode,
2455 html: *mut _xmlNode,
2456 head: *mut _xmlNode,
2457 body: *mut _xmlNode,
2458 in_head: bool,
2459 in_body: bool,
2460 html_created: bool,
2461 head_created: bool,
2462 body_created: bool,
2463 seen_body_content: bool,
2464 input: *mut u8,
2466 input_pos: usize,
2467 input_len: usize,
2468 line: c_int,
2469 err: bool,
2470 filename: *mut c_char,
2471 encoding: *mut c_char,
2472 options: c_int,
2474 sax: *mut _xmlSAXHandler,
2475 user_data: *mut c_void,
2476}
2477
2478unsafe fn html_ctxt_alloc() -> *mut HtmlOpaqueCtxt {
2481 let mem = xmlMallocZero(size_of::<HtmlOpaqueCtxt>()) as *mut HtmlOpaqueCtxt;
2482 if mem.is_null() {
2483 return ptr::null_mut();
2484 }
2485 unsafe {
2486 ptr::write(
2487 mem,
2488 HtmlOpaqueCtxt {
2489 doc: ptr::null_mut(),
2490 current: ptr::null_mut(),
2491 html: ptr::null_mut(),
2492 head: ptr::null_mut(),
2493 body: ptr::null_mut(),
2494 in_head: false,
2495 in_body: false,
2496 html_created: false,
2497 head_created: false,
2498 body_created: false,
2499 seen_body_content: false,
2500 input: ptr::null_mut(),
2501 input_pos: 0,
2502 input_len: 0,
2503 line: 1,
2504 err: false,
2505 filename: ptr::null_mut(),
2506 encoding: ptr::null_mut(),
2507 options: 0,
2508 sax: ptr::null_mut(),
2509 user_data: ptr::null_mut(),
2510 },
2511 );
2512 }
2513 mem
2514}
2515
2516unsafe fn html_ctxt_set_input(ctxt: *mut HtmlOpaqueCtxt, buffer: *const c_char, size: c_int) {
2518 if buffer.is_null() || size <= 0 {
2519 return;
2520 }
2521 let len = size as usize;
2522 let nb = xmlMallocImpl(len) as *mut u8;
2523 if nb.is_null() {
2524 return;
2525 }
2526 unsafe {
2527 ptr::copy_nonoverlapping(buffer as *const u8, nb, len);
2528 (*ctxt).input = nb;
2529 (*ctxt).input_len = len;
2530 (*ctxt).input_pos = 0;
2531 }
2532}
2533
2534#[no_mangle]
2542pub unsafe extern "C" fn htmlNewSAXParserCtxt(
2543 sax: *const _xmlSAXHandler,
2544 userData: *mut c_void,
2545) -> *mut c_void {
2546 let ctxt = unsafe { html_ctxt_alloc() };
2547 if ctxt.is_null() {
2548 return ptr::null_mut();
2549 }
2550 unsafe {
2551 (*ctxt).sax = sax as *mut _xmlSAXHandler;
2552 (*ctxt).user_data = userData;
2553 }
2554 ctxt as *mut c_void
2555}
2556
2557#[no_mangle]
2565pub unsafe extern "C" fn htmlNewParserCtxt() -> *mut c_void {
2566 unsafe { htmlNewSAXParserCtxt(ptr::null(), ptr::null_mut()) }
2567}
2568
2569#[no_mangle]
2578pub unsafe extern "C" fn htmlCreateMemoryParserCtxt(
2579 buffer: *const c_char,
2580 size: c_int,
2581) -> *mut c_void {
2582 if buffer.is_null() || size <= 0 {
2583 return ptr::null_mut();
2584 }
2585 let ctxt = unsafe { html_ctxt_alloc() };
2586 if ctxt.is_null() {
2587 return ptr::null_mut();
2588 }
2589 unsafe { html_ctxt_set_input(ctxt, buffer, size) };
2590 if unsafe { (*ctxt).input.is_null() } {
2591 unsafe { crate::xml::html::free_parser_ctxt(ctxt as *mut c_void) };
2592 return ptr::null_mut();
2593 }
2594 ctxt as *mut c_void
2595}
2596
2597#[no_mangle]
2607pub unsafe extern "C" fn htmlCreatePushParserCtxt(
2608 sax: *mut _xmlSAXHandler,
2609 user_data: *mut c_void,
2610 chunk: *const c_char,
2611 size: c_int,
2612 filename: *const c_char,
2613 _enc: xmlCharEncoding,
2614) -> *mut c_void {
2615 let ctxt = unsafe { html_ctxt_alloc() };
2616 if ctxt.is_null() {
2617 return ptr::null_mut();
2618 }
2619 unsafe {
2620 (*ctxt).sax = sax;
2621 (*ctxt).user_data = user_data;
2622 if !filename.is_null() {
2623 (*ctxt).filename = c_strdup(filename);
2624 }
2625 if size > 0 && !chunk.is_null() {
2626 html_ctxt_set_input(ctxt, chunk, size);
2627 } else {
2628 let nb = xmlMallocImpl(1) as *mut u8;
2631 if !nb.is_null() {
2632 (*ctxt).input = nb;
2633 (*ctxt).input_len = 0;
2634 (*ctxt).input_pos = 0;
2635 }
2636 }
2637 }
2638 ctxt as *mut c_void
2639}
2640
2641#[no_mangle]
2649pub unsafe extern "C" fn htmlCtxtReset(ctxt: *mut c_void) {
2650 if ctxt.is_null() {
2651 return;
2652 }
2653 let c = ctxt as *mut HtmlOpaqueCtxt;
2654 unsafe {
2655 if !(*c).input.is_null() {
2656 xmlFreeImpl((*c).input as *mut c_void);
2657 }
2658 (*c).input = ptr::null_mut();
2659 (*c).input_len = 0;
2660 (*c).input_pos = 0;
2661 (*c).doc = ptr::null_mut();
2662 (*c).options = 0;
2663 (*c).line = 1;
2664 (*c).err = false;
2665 }
2666}
2667
2668#[no_mangle]
2679pub unsafe extern "C" fn htmlCtxtUseOptions(ctxt: *mut c_void, options: c_int) -> c_int {
2680 if ctxt.is_null() {
2681 return -1;
2682 }
2683 let c = ctxt as *mut HtmlOpaqueCtxt;
2684 unsafe {
2686 (*c).options = ((*c).options & HTML_OPTIONS_KEEP_MASK) | (options & HTML_OPTIONS_ALL_MASK);
2687 }
2688 options & !HTML_OPTIONS_ALL_MASK & !crate::abi::types::XML_PARSE_NOENT
2691}
2692
2693#[no_mangle]
2702pub unsafe extern "C" fn htmlParseDocument(ctxt: *mut c_void) -> c_int {
2703 if ctxt.is_null() {
2704 return -1;
2705 }
2706 let c = ctxt as *mut HtmlOpaqueCtxt;
2707 if unsafe { (*c).input.is_null() } {
2708 return -1;
2709 }
2710 let doc = unsafe { html::parse_memory((*c).input as *const c_char, (*c).input_len as c_int) };
2711 unsafe { (*c).doc = doc };
2712 if doc.is_null() {
2713 -1
2714 } else {
2715 0
2716 }
2717}
2718
2719#[no_mangle]
2730pub unsafe extern "C" fn htmlParseChunk(
2731 ctxt: *mut c_void,
2732 chunk: *const c_char,
2733 size: c_int,
2734 terminate: c_int,
2735) -> c_int {
2736 if ctxt.is_null() || size < 0 || (size > 0 && chunk.is_null()) {
2737 return XML_ERR_ARGUMENT;
2738 }
2739 let c = ctxt as *mut HtmlOpaqueCtxt;
2740 if unsafe { (*c).input.is_null() } {
2741 return XML_ERR_ARGUMENT;
2742 }
2743
2744 if size > 0 {
2745 let new_len = unsafe { (*c).input_len }.wrapping_add(size as usize);
2746 let nb = unsafe { xmlReallocImpl((*c).input as *mut c_void, new_len) } as *mut u8;
2747 if nb.is_null() {
2748 return XML_ERR_NO_MEMORY;
2749 }
2750 unsafe {
2751 ptr::copy_nonoverlapping(chunk as *const u8, nb.add((*c).input_len), size as usize);
2752 (*c).input = nb;
2753 (*c).input_len = new_len;
2754 }
2755 }
2756
2757 if terminate != 0 {
2758 let doc =
2759 unsafe { html::parse_memory((*c).input as *const c_char, (*c).input_len as c_int) };
2760 unsafe {
2761 (*c).doc = doc;
2762 xmlFreeImpl((*c).input as *mut c_void);
2764 (*c).input = ptr::null_mut();
2765 (*c).input_len = 0;
2766 }
2767 }
2768 XML_ERR_OK
2769}
2770
2771#[no_mangle]
2779pub unsafe extern "C" fn htmlCtxtParseDocument(
2780 ctxt: *mut c_void,
2781 input: *mut _xmlParserInput,
2782) -> *mut _xmlDoc {
2783 if ctxt.is_null() || input.is_null() {
2784 return ptr::null_mut();
2785 }
2786 let cur = unsafe { (*input).cur };
2787 let end = unsafe { (*input).end };
2788 if cur.is_null() {
2789 return ptr::null_mut();
2790 }
2791 let len = (end as usize).wrapping_sub(cur as usize) as c_int;
2792 if len <= 0 {
2793 return ptr::null_mut();
2794 }
2795 let doc = unsafe { html::parse_memory(cur as *const c_char, len) };
2796 let c = ctxt as *mut HtmlOpaqueCtxt;
2797 unsafe {
2798 (*c).doc = doc;
2799 }
2800 doc
2801}
2802
2803unsafe fn html_ctxt_finish_read(
2810 ctxt: *mut c_void,
2811 doc: *mut _xmlDoc,
2812 url: *const c_char,
2813) -> *mut _xmlDoc {
2814 if ctxt.is_null() {
2815 return doc;
2816 }
2817 let c = ctxt as *mut HtmlOpaqueCtxt;
2818 unsafe {
2819 (*c).doc = doc;
2820 if !doc.is_null() && !url.is_null() {
2821 (*doc).URL = c_strdup(url) as *mut xmlChar;
2822 }
2823 }
2824 doc
2825}
2826
2827#[no_mangle]
2836pub unsafe extern "C" fn htmlCtxtReadMemory(
2837 ctxt: *mut c_void,
2838 buffer: *const c_char,
2839 size: c_int,
2840 URL: *const c_char,
2841 _encoding: *const c_char,
2842 options: c_int,
2843) -> *mut _xmlDoc {
2844 if ctxt.is_null() || size < 0 {
2845 return ptr::null_mut();
2846 }
2847 unsafe { htmlCtxtReset(ctxt) };
2848 unsafe { htmlCtxtUseOptions(ctxt, options) };
2849 let doc = unsafe { html::parse_memory(buffer, size) };
2850 unsafe { html_ctxt_finish_read(ctxt, doc, URL) }
2851}
2852
2853#[no_mangle]
2862pub unsafe extern "C" fn htmlCtxtReadDoc(
2863 ctxt: *mut c_void,
2864 str: *const xmlChar,
2865 URL: *const c_char,
2866 encoding: *const c_char,
2867 options: c_int,
2868) -> *mut _xmlDoc {
2869 if ctxt.is_null() {
2870 return ptr::null_mut();
2871 }
2872 unsafe { htmlCtxtReset(ctxt) };
2873 unsafe { htmlCtxtUseOptions(ctxt, options) };
2874 let doc = unsafe { html::parse_doc(str, encoding) };
2875 unsafe { html_ctxt_finish_read(ctxt, doc, URL) }
2876}
2877
2878#[no_mangle]
2888pub unsafe extern "C" fn htmlCtxtReadFile(
2889 ctxt: *mut c_void,
2890 filename: *const c_char,
2891 encoding: *const c_char,
2892 options: c_int,
2893) -> *mut _xmlDoc {
2894 if ctxt.is_null() {
2895 return ptr::null_mut();
2896 }
2897 unsafe { htmlCtxtReset(ctxt) };
2898 unsafe { htmlCtxtUseOptions(ctxt, options) };
2899 let doc = unsafe { html::parse_file(filename, encoding) };
2900 unsafe { html_ctxt_finish_read(ctxt, doc, filename) }
2901}
2902
2903unsafe fn html_read_fd(fd: c_int) -> Vec<u8> {
2905 let mut buf = Vec::new();
2906 let mut tmp = [0u8; 4096];
2907 loop {
2908 let n = libc::read(fd, tmp.as_mut_ptr() as *mut c_void, tmp.len());
2909 if n <= 0 {
2910 break;
2911 }
2912 buf.extend_from_slice(&tmp[..n as usize]);
2913 }
2914 buf
2915}
2916
2917unsafe fn html_read_io(ioread: Option<xmlInputReadCallback>, ioctx: *mut c_void) -> Vec<u8> {
2919 let mut buf = Vec::new();
2920 let mut tmp = [0u8; 4096];
2921 if let Some(read) = ioread {
2922 loop {
2923 let n = unsafe { read(ioctx, tmp.as_mut_ptr() as *mut c_char, tmp.len() as c_int) };
2924 if n <= 0 {
2925 break;
2926 }
2927 buf.extend_from_slice(&tmp[..n as usize]);
2928 }
2929 }
2930 buf
2931}
2932
2933#[no_mangle]
2942pub unsafe extern "C" fn htmlCtxtReadFd(
2943 ctxt: *mut c_void,
2944 fd: c_int,
2945 URL: *const c_char,
2946 _encoding: *const c_char,
2947 options: c_int,
2948) -> *mut _xmlDoc {
2949 if ctxt.is_null() {
2950 return ptr::null_mut();
2951 }
2952 unsafe { htmlCtxtReset(ctxt) };
2953 unsafe { htmlCtxtUseOptions(ctxt, options) };
2954 let data = unsafe { html_read_fd(fd) };
2955 let doc = unsafe { html::parse_memory(data.as_ptr() as *const c_char, data.len() as c_int) };
2956 unsafe { html_ctxt_finish_read(ctxt, doc, URL) }
2957}
2958
2959#[no_mangle]
2969pub unsafe extern "C" fn htmlCtxtReadIO(
2970 ctxt: *mut c_void,
2971 ioread: Option<xmlInputReadCallback>,
2972 _ioclose: Option<xmlInputCloseCallback>,
2973 ioctx: *mut c_void,
2974 URL: *const c_char,
2975 _encoding: *const c_char,
2976 options: c_int,
2977) -> *mut _xmlDoc {
2978 if ctxt.is_null() {
2979 return ptr::null_mut();
2980 }
2981 unsafe { htmlCtxtReset(ctxt) };
2982 unsafe { htmlCtxtUseOptions(ctxt, options) };
2983 let data = unsafe { html_read_io(ioread, ioctx) };
2984 let doc = unsafe { html::parse_memory(data.as_ptr() as *const c_char, data.len() as c_int) };
2985 unsafe { html_ctxt_finish_read(ctxt, doc, URL) }
2986}
2987
2988#[no_mangle]
2997pub unsafe extern "C" fn htmlReadMemory(
2998 buffer: *const c_char,
2999 size: c_int,
3000 url: *const c_char,
3001 encoding: *const c_char,
3002 options: c_int,
3003) -> *mut _xmlDoc {
3004 if size < 0 {
3005 return ptr::null_mut();
3006 }
3007 let ctxt = unsafe { htmlNewParserCtxt() };
3008 if ctxt.is_null() {
3009 return ptr::null_mut();
3010 }
3011 let doc = unsafe { htmlCtxtReadMemory(ctxt, buffer, size, url, encoding, options) };
3012 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3013 doc
3014}
3015
3016#[no_mangle]
3026pub unsafe extern "C" fn htmlReadDoc(
3027 str: *const xmlChar,
3028 url: *const c_char,
3029 encoding: *const c_char,
3030 options: c_int,
3031) -> *mut _xmlDoc {
3032 let ctxt = unsafe { htmlNewParserCtxt() };
3033 if ctxt.is_null() {
3034 return ptr::null_mut();
3035 }
3036 let doc = unsafe { htmlCtxtReadDoc(ctxt, str, url, encoding, options) };
3037 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3038 doc
3039}
3040
3041#[no_mangle]
3050pub unsafe extern "C" fn htmlReadFile(
3051 filename: *const c_char,
3052 encoding: *const c_char,
3053 options: c_int,
3054) -> *mut _xmlDoc {
3055 let ctxt = unsafe { htmlNewParserCtxt() };
3056 if ctxt.is_null() {
3057 return ptr::null_mut();
3058 }
3059 let doc = unsafe { htmlCtxtReadFile(ctxt, filename, encoding, options) };
3060 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3061 doc
3062}
3063
3064#[no_mangle]
3072pub unsafe extern "C" fn htmlReadFd(
3073 fd: c_int,
3074 url: *const c_char,
3075 encoding: *const c_char,
3076 options: c_int,
3077) -> *mut _xmlDoc {
3078 let ctxt = unsafe { htmlNewParserCtxt() };
3079 if ctxt.is_null() {
3080 return ptr::null_mut();
3081 }
3082 let doc = unsafe { htmlCtxtReadFd(ctxt, fd, url, encoding, options) };
3083 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3084 doc
3085}
3086
3087#[no_mangle]
3097pub unsafe extern "C" fn htmlReadIO(
3098 ioread: Option<xmlInputReadCallback>,
3099 ioclose: Option<xmlInputCloseCallback>,
3100 ioctx: *mut c_void,
3101 url: *const c_char,
3102 encoding: *const c_char,
3103 options: c_int,
3104) -> *mut _xmlDoc {
3105 let ctxt = unsafe { htmlNewParserCtxt() };
3106 if ctxt.is_null() {
3107 return ptr::null_mut();
3108 }
3109 let doc = unsafe { htmlCtxtReadIO(ctxt, ioread, ioclose, ioctx, url, encoding, options) };
3110 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3111 doc
3112}
3113
3114#[no_mangle]
3125pub unsafe extern "C" fn htmlSAXParseDoc(
3126 cur: *const xmlChar,
3127 encoding: *const c_char,
3128 sax: *mut _xmlSAXHandler,
3129 userData: *mut c_void,
3130) -> *mut _xmlDoc {
3131 if cur.is_null() {
3132 return ptr::null_mut();
3133 }
3134 let ctxt = unsafe { htmlNewSAXParserCtxt(sax, userData) };
3135 if ctxt.is_null() {
3136 return ptr::null_mut();
3137 }
3138 let doc = unsafe { htmlCtxtReadDoc(ctxt, cur, ptr::null(), encoding, 0) };
3139 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3140 doc
3141}
3142
3143#[no_mangle]
3154pub unsafe extern "C" fn htmlSAXParseFile(
3155 filename: *const c_char,
3156 encoding: *const c_char,
3157 sax: *mut _xmlSAXHandler,
3158 userData: *mut c_void,
3159) -> *mut _xmlDoc {
3160 let ctxt = unsafe { htmlNewSAXParserCtxt(sax, userData) };
3161 if ctxt.is_null() {
3162 return ptr::null_mut();
3163 }
3164 let doc = unsafe { htmlCtxtReadFile(ctxt, filename, encoding, 0) };
3165 unsafe { crate::xml::html::free_parser_ctxt(ctxt) };
3166 doc
3167}
3168
3169#[no_mangle]
3180pub unsafe extern "C" fn htmlParseElement(ctxt: *mut c_void) {
3181 if ctxt.is_null() {
3182 return;
3183 }
3184 let c = ctxt as *mut HtmlOpaqueCtxt;
3185 if unsafe { (*c).input.is_null() } {
3186 return;
3187 }
3188 let doc = unsafe { html::parse_memory((*c).input as *const c_char, (*c).input_len as c_int) };
3189 unsafe {
3190 (*c).doc = doc;
3191 }
3192}
3193
3194#[no_mangle]
3207pub unsafe extern "C" fn htmlNewDocNoDtD(
3208 URI: *const xmlChar,
3209 publicId: *const xmlChar,
3210) -> *mut _xmlDoc {
3211 let doc = unsafe { html::new_doc_no_dtd(ptr::null()) };
3212 if doc.is_null() {
3213 return ptr::null_mut();
3214 }
3215 unsafe {
3216 (*doc).standalone = 1;
3219 (*doc).charset = crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_UTF8 as c_int;
3220 (*doc).properties = crate::abi::types::xmlDocProperties::XML_DOC_HTML as c_int
3221 | crate::abi::types::xmlDocProperties::XML_DOC_USERBUILT as c_int;
3222 if !publicId.is_null() || !URI.is_null() {
3223 let dtd = crate::xml::dtd::create_int_subset(
3224 doc,
3225 b"html\0" as *const u8 as *const xmlChar,
3226 publicId,
3227 URI,
3228 );
3229 if dtd.is_null() {
3230 tree::free_doc(doc);
3231 return ptr::null_mut();
3232 }
3233 }
3234 }
3235 doc
3236}
3237
3238#[no_mangle]
3253pub unsafe extern "C" fn htmlNewDoc(
3254 URI: *const xmlChar,
3255 ExternalID: *const xmlChar,
3256) -> *mut _xmlDoc {
3257 let doc = unsafe { html::new_doc(ptr::null()) };
3258 if doc.is_null() {
3259 return ptr::null_mut();
3260 }
3261 unsafe {
3262 (*doc).standalone = 1;
3265 (*doc).charset = crate::abi::types::xmlCharEncoding::XML_CHAR_ENCODING_UTF8 as c_int;
3266 (*doc).properties = crate::abi::types::xmlDocProperties::XML_DOC_HTML as c_int
3267 | crate::abi::types::xmlDocProperties::XML_DOC_USERBUILT as c_int;
3268 if URI.is_null() && ExternalID.is_null() {
3269 let dtd = crate::xml::dtd::create_int_subset(
3270 doc,
3271 b"html\0" as *const u8 as *const xmlChar,
3272 b"-//W3C//DTD HTML 4.0 Transitional//EN\0" as *const u8 as *const xmlChar,
3273 b"http://www.w3.org/TR/REC-html40/loose.dtd\0" as *const u8 as *const xmlChar,
3274 );
3275 if dtd.is_null() {
3276 tree::free_doc(doc);
3277 return ptr::null_mut();
3278 }
3279 } else if !ExternalID.is_null() || !URI.is_null() {
3280 let dtd = crate::xml::dtd::create_int_subset(
3281 doc,
3282 b"html\0" as *const u8 as *const xmlChar,
3283 ExternalID,
3284 URI,
3285 );
3286 if dtd.is_null() {
3287 tree::free_doc(doc);
3288 return ptr::null_mut();
3289 }
3290 }
3291 }
3292 doc
3293}
3294
3295unsafe fn html_find_first_child(node: *mut _xmlNode, name: &[u8]) -> *mut _xmlNode {
3301 let mut c = unsafe { (*node).children };
3302 while !c.is_null() {
3303 let n = unsafe { &*c };
3304 if n.type_ == XML_ELEMENT_NODE as c_int
3305 && !n.name.is_null()
3306 && unsafe { xmlstr_to_bytes(n.name) }.eq_ignore_ascii_case(name)
3307 {
3308 return c;
3309 }
3310 c = unsafe { (*c).next };
3311 }
3312 ptr::null_mut()
3313}
3314
3315unsafe fn html_find_head(doc: *mut _xmlDoc) -> *mut _xmlNode {
3318 if doc.is_null() {
3319 return ptr::null_mut();
3320 }
3321 let html = unsafe { html_find_first_child(doc as *mut _xmlNode, b"html") };
3322 if html.is_null() {
3323 return ptr::null_mut();
3324 }
3325 unsafe { html_find_first_child(html, b"head") }
3326}
3327
3328unsafe fn html_find_meta_encoding_attr(elem: *mut _xmlNode) -> (*mut _xmlAttr, bool) {
3331 let n = unsafe { &*elem };
3332 if n.type_ != XML_ELEMENT_NODE as c_int || n.name.is_null() {
3333 return (ptr::null_mut(), false);
3334 }
3335 if !unsafe { xmlstr_to_bytes(n.name) }.eq_ignore_ascii_case(b"meta") {
3336 return (ptr::null_mut(), false);
3337 }
3338
3339 let mut content_attr: *mut _xmlAttr = ptr::null_mut();
3340 let mut is_content_type = false;
3341 let mut attr = n.properties;
3342 while !attr.is_null() {
3343 let a = unsafe { &*attr };
3344 if a.ns.is_null() && !a.name.is_null() {
3345 let nm = unsafe { xmlstr_to_bytes(a.name) };
3346 if nm.eq_ignore_ascii_case(b"charset") {
3347 return (attr, false);
3348 }
3349 if nm.eq_ignore_ascii_case(b"content") {
3350 content_attr = attr;
3351 }
3352 if nm.eq_ignore_ascii_case(b"http-equiv")
3353 && !a.children.is_null()
3354 && unsafe { (*(a.children)).type_ } == XML_TEXT_NODE as c_int
3355 && unsafe { (*(a.children)).next }.is_null()
3356 && !unsafe { (*(a.children)).content }.is_null()
3357 && unsafe { xmlstr_to_bytes((*(a.children)).content) }
3358 .eq_ignore_ascii_case(b"Content-Type")
3359 {
3360 is_content_type = true;
3361 }
3362 }
3363 attr = unsafe { (*attr).next };
3364 }
3365 if is_content_type && !content_attr.is_null() {
3366 (content_attr, true)
3367 } else {
3368 (ptr::null_mut(), false)
3369 }
3370}
3371
3372unsafe fn html_parse_content_type(val: *const xmlChar) -> Option<(usize, usize, usize)> {
3375 let bytes = unsafe { xmlstr_to_bytes(val) };
3376 let n = bytes.len();
3377 let at = |i: usize| -> u8 {
3378 if i < n {
3379 bytes[i]
3380 } else {
3381 0
3382 }
3383 };
3384
3385 let mut p = 0usize;
3386 loop {
3387 loop {
3389 let ch = at(p);
3390 if ch == b'c' || ch == b'C' {
3391 break;
3392 }
3393 if ch == 0 {
3394 return None;
3395 }
3396 p += 1;
3397 }
3398 p += 1;
3399
3400 let mut ok = true;
3402 for (k, want) in b"harset".iter().enumerate() {
3403 if at(p + k).to_ascii_lowercase() != *want {
3404 ok = false;
3405 break;
3406 }
3407 }
3408 if !ok {
3409 continue;
3410 }
3411 p += 6;
3412 while is_ws_html(at(p)) {
3413 p += 1;
3414 }
3415 if at(p) != b'=' {
3416 continue;
3417 }
3418 p += 1;
3419 while is_ws_html(at(p)) {
3420 p += 1;
3421 }
3422 if at(p) == 0 {
3423 return None;
3424 }
3425
3426 let (start, mut end): (usize, usize);
3427 if at(p) == b'"' || at(p) == b'\'' {
3428 let quote = at(p);
3429 p += 1;
3430 while is_ws_html(at(p)) {
3431 p += 1;
3432 }
3433 start = p;
3434 end = start;
3435 loop {
3436 if at(p) == 0 {
3437 return None;
3438 }
3439 if !is_ws_html(at(p)) {
3440 end = p + 1;
3441 }
3442 if at(p) == quote {
3443 break;
3444 }
3445 p += 1;
3446 }
3447 } else {
3448 start = p;
3449 while at(p) != 0 && at(p) != b';' && !is_ws_html(at(p)) {
3450 p += 1;
3451 }
3452 end = p;
3453 }
3454 let size = n;
3455 return Some((start, end, size));
3456 }
3457}
3458
3459#[no_mangle]
3471pub unsafe extern "C" fn htmlGetMetaEncoding(doc: *mut _xmlDoc) -> *const xmlChar {
3472 let head = unsafe { html_find_head(doc) };
3473 if head.is_null() {
3474 return ptr::null();
3475 }
3476 let mut node = unsafe { (*head).children };
3477 while !node.is_null() {
3478 let (attr, is_content_type) = unsafe { html_find_meta_encoding_attr(node) };
3479 if !attr.is_null() {
3480 let a = unsafe { &*attr };
3481 let val = if !a.children.is_null()
3482 && unsafe { (*(a.children)).type_ } == XML_TEXT_NODE as c_int
3483 && unsafe { (*(a.children)).next }.is_null()
3484 && !unsafe { (*(a.children)).content }.is_null()
3485 {
3486 unsafe { (*(a.children)).content }
3487 } else {
3488 b"\0" as *const u8 as *const xmlChar
3489 };
3490 if !is_content_type {
3491 let bytes = unsafe { xmlstr_to_bytes(val) };
3492 let mut start = 0usize;
3493 while start < bytes.len() && is_ws_html(bytes[start]) {
3494 start += 1;
3495 }
3496 return unsafe { val.add(start) };
3497 } else if let Some((start, _, _)) = unsafe { html_parse_content_type(val) } {
3498 return unsafe { val.add(start) };
3499 }
3500 }
3501 node = unsafe { (*node).next };
3502 }
3503 ptr::null()
3504}
3505
3506unsafe fn html_update_meta_encoding(
3509 attr_value: *const xmlChar,
3510 start: usize,
3511 end: usize,
3512 size: usize,
3513 encoding: &[u8],
3514) -> *mut xmlChar {
3515 let enc: &[u8] = if encoding.eq_ignore_ascii_case(b"HTML") {
3517 b"ASCII"
3518 } else {
3519 encoding
3520 };
3521 let bytes = unsafe { xmlstr_to_bytes(attr_value) };
3522 let e = end.min(bytes.len()).min(size);
3523 let s = start.min(e);
3524 let total = size - (e - s) + enc.len();
3525 let new_val = xmlMallocImpl(total + 1) as *mut xmlChar;
3526 if new_val.is_null() {
3527 return ptr::null_mut();
3528 }
3529 unsafe {
3530 let mut p = new_val;
3531 ptr::copy_nonoverlapping(bytes.as_ptr(), p, s);
3532 p = p.add(s);
3533 ptr::copy_nonoverlapping(enc.as_ptr(), p, enc.len());
3534 p = p.add(enc.len());
3535 ptr::copy_nonoverlapping(bytes.as_ptr().add(e), p, size - e);
3536 *new_val.add(total) = 0;
3537 }
3538 new_val
3539}
3540
3541unsafe fn html_set_attr_content(attr: *mut _xmlAttr, content: *const xmlChar) -> c_int {
3544 if attr.is_null() {
3545 return -1;
3546 }
3547 unsafe {
3548 if !(*attr).children.is_null() {
3549 tree::free_node_list((*attr).children);
3550 (*attr).children = ptr::null_mut();
3551 (*attr).last = ptr::null_mut();
3552 }
3553 let text = tree::new_text(content);
3554 if text.is_null() {
3555 return -1;
3556 }
3557 (*text).parent = attr as *mut _xmlNode;
3558 (*text).doc = (*attr).doc;
3559 (*attr).children = text;
3560 (*attr).last = text;
3561 }
3562 0
3563}
3564
3565#[no_mangle]
3573pub unsafe extern "C" fn htmlSetMetaEncoding(doc: *mut _xmlDoc, encoding: *const xmlChar) -> c_int {
3574 if encoding.is_null() {
3575 return 1;
3576 }
3577 let head = unsafe { html_find_head(doc) };
3578 if head.is_null() {
3579 return 1;
3580 }
3581 let enc_bytes = unsafe { xmlstr_to_bytes(encoding) }.to_vec();
3582
3583 let mut found = 0;
3584 let mut meta = unsafe { (*head).children };
3585 while !meta.is_null() {
3586 let (attr, is_content_type) = unsafe { html_find_meta_encoding_attr(meta) };
3587 if !attr.is_null() {
3588 let a = unsafe { &*attr };
3589 let val = if !a.children.is_null()
3590 && unsafe { (*(a.children)).type_ } == XML_TEXT_NODE as c_int
3591 && unsafe { (*(a.children)).next }.is_null()
3592 && !unsafe { (*(a.children)).content }.is_null()
3593 {
3594 unsafe { (*(a.children)).content }
3595 } else {
3596 b"\0" as *const u8 as *const xmlChar
3597 };
3598 found = 1;
3599 let off = if is_content_type {
3600 unsafe { html_parse_content_type(val) }
3601 } else {
3602 let bytes = unsafe { xmlstr_to_bytes(val) };
3603 let mut start = 0usize;
3604 let mut end = bytes.len();
3605 while start < end && is_ws_html(bytes[start]) {
3606 start += 1;
3607 }
3608 while end > start && is_ws_html(bytes[end - 1]) {
3609 end -= 1;
3610 }
3611 Some((start, end, bytes.len()))
3612 };
3613 if let Some((start, end, size)) = off {
3614 let new_val =
3615 unsafe { html_update_meta_encoding(val, start, end, size, &enc_bytes) };
3616 if new_val.is_null() {
3617 return -1;
3618 }
3619 let ret = unsafe { html_set_attr_content(attr, new_val) };
3620 unsafe { xmlFreeImpl(new_val as *mut c_void) };
3621 if ret < 0 {
3622 return -1;
3623 }
3624 } else {
3625 return -1;
3626 }
3627 }
3628 meta = unsafe { (*meta).next };
3629 }
3630
3631 if found != 0 {
3632 return 0;
3633 }
3634
3635 let meta_node =
3637 unsafe { tree::new_node(ptr::null_mut(), b"meta\0" as *const u8 as *const xmlChar) };
3638 if meta_node.is_null() {
3639 return -1;
3640 }
3641 unsafe {
3642 (*meta_node).doc = (*head).doc;
3643 }
3644 let prop = unsafe {
3645 tree::set_prop(
3646 meta_node,
3647 b"charset\0" as *const u8 as *const xmlChar,
3648 encoding,
3649 )
3650 };
3651 if prop.is_null() {
3652 unsafe { tree::free_node(meta_node) };
3653 return -1;
3654 }
3655 if unsafe { (*head).children }.is_null() {
3656 unsafe { tree::add_child(head, meta_node) };
3657 } else {
3658 unsafe { tree::add_sibling_before((*head).children, meta_node) };
3659 }
3660 0
3661}
3662
3663unsafe fn html_serialize_to_buffer(node: *mut _xmlNode, format: c_int) -> *mut _xmlBuffer {
3670 let buf = io::buf_create(0);
3671 if buf.is_null() {
3672 return ptr::null_mut();
3673 }
3674 unsafe { html::serialize_node(node, buf, format, 0) };
3675 buf
3676}
3677
3678unsafe fn html_serialize_to_obuf(obuf: *mut _xmlOutputBuffer, node: *mut _xmlNode, format: c_int) {
3681 if obuf.is_null() || node.is_null() {
3682 return;
3683 }
3684 let buf = unsafe { html_serialize_to_buffer(node, format) };
3685 if buf.is_null() {
3686 return;
3687 }
3688 let len = io::buf_length(buf);
3689 if len > 0 {
3690 let content = io::buf_content(buf);
3691 unsafe {
3692 io::output_buffer_write(obuf, len, content as *const c_char);
3693 }
3694 }
3695 io::buf_free(buf);
3696}
3697
3698#[no_mangle]
3706pub unsafe extern "C" fn htmlNodeDump(
3707 buf: *mut _xmlBuffer,
3708 _doc: *mut _xmlDoc,
3709 cur: *mut _xmlNode,
3710) -> c_int {
3711 if buf.is_null() || cur.is_null() {
3712 return -1;
3713 }
3714 let before = io::buf_length(buf);
3715 unsafe { html::serialize_node(cur, buf, 1, 0) };
3716 let after = io::buf_length(buf);
3717 if after < 0 || before < 0 {
3718 return -1;
3719 }
3720 after - before
3721}
3722
3723#[no_mangle]
3731pub unsafe extern "C" fn htmlNodeDumpFile(out: *mut c_void, doc: *mut _xmlDoc, cur: *mut _xmlNode) {
3732 unsafe { htmlNodeDumpFileFormat(out, doc, cur, ptr::null(), 1) };
3733}
3734
3735#[no_mangle]
3744pub unsafe extern "C" fn htmlNodeDumpFileFormat(
3745 out: *mut c_void,
3746 _doc: *mut _xmlDoc,
3747 cur: *mut _xmlNode,
3748 _encoding: *const c_char,
3749 format: c_int,
3750) -> c_int {
3751 let obuf = io::output_buffer_create_file(out as *mut libc::FILE, ptr::null_mut());
3752 if obuf.is_null() {
3753 return -1;
3754 }
3755 unsafe { html_serialize_to_obuf(obuf, cur, format) };
3756 io::output_buffer_close(obuf)
3757}
3758
3759#[no_mangle]
3768pub unsafe extern "C" fn htmlNodeDumpOutput(
3769 buf: *mut _xmlOutputBuffer,
3770 _doc: *mut _xmlDoc,
3771 cur: *mut _xmlNode,
3772 _encoding: *const c_char,
3773) {
3774 unsafe { html_serialize_to_obuf(buf, cur, 1) };
3775}
3776
3777#[no_mangle]
3786pub unsafe extern "C" fn htmlNodeDumpFormatOutput(
3787 buf: *mut _xmlOutputBuffer,
3788 _doc: *mut _xmlDoc,
3789 cur: *mut _xmlNode,
3790 _encoding: *const c_char,
3791 format: c_int,
3792) {
3793 unsafe { html_serialize_to_obuf(buf, cur, format) };
3794}
3795
3796#[no_mangle]
3805pub unsafe extern "C" fn htmlDocContentDumpOutput(
3806 buf: *mut _xmlOutputBuffer,
3807 cur: *mut _xmlDoc,
3808 _encoding: *const c_char,
3809) {
3810 unsafe { html_serialize_to_obuf(buf, cur as *mut _xmlNode, 1) };
3811}
3812
3813#[no_mangle]
3822pub unsafe extern "C" fn htmlDocContentDumpFormatOutput(
3823 buf: *mut _xmlOutputBuffer,
3824 cur: *mut _xmlDoc,
3825 _encoding: *const c_char,
3826 format: c_int,
3827) {
3828 unsafe { html_serialize_to_obuf(buf, cur as *mut _xmlNode, format) };
3829}
3830
3831#[no_mangle]
3841pub unsafe extern "C" fn htmlDocDumpMemoryFormat(
3842 cur: *mut _xmlDoc,
3843 mem: *mut *mut xmlChar,
3844 size: *mut c_int,
3845 format: c_int,
3846) {
3847 if mem.is_null() || size.is_null() {
3848 return;
3849 }
3850 unsafe {
3851 *mem = ptr::null_mut();
3852 *size = 0;
3853 }
3854 if cur.is_null() {
3855 return;
3856 }
3857 let buf = unsafe { html_serialize_to_buffer(cur as *mut _xmlNode, format) };
3858 if buf.is_null() {
3859 return;
3860 }
3861 let len = io::buf_length(buf);
3862 if len > 0 {
3863 let content = io::buf_content(buf);
3864 unsafe {
3865 *mem = xml_strndup(content, len as usize);
3866 if !(*mem).is_null() {
3867 *size = len;
3868 }
3869 }
3870 }
3871 io::buf_free(buf);
3872}
3873
3874#[no_mangle]
3882pub unsafe extern "C" fn htmlDocDumpMemory(
3883 cur: *mut _xmlDoc,
3884 mem: *mut *mut xmlChar,
3885 size: *mut c_int,
3886) {
3887 unsafe { htmlDocDumpMemoryFormat(cur, mem, size, 1) };
3888}
3889
3890#[no_mangle]
3898pub unsafe extern "C" fn htmlDocDump(f: *mut c_void, cur: *mut _xmlDoc) -> c_int {
3899 if f.is_null() || cur.is_null() {
3900 return -1;
3901 }
3902 let obuf = io::output_buffer_create_file(f as *mut libc::FILE, ptr::null_mut());
3903 if obuf.is_null() {
3904 return -1;
3905 }
3906 unsafe { html_serialize_to_obuf(obuf, cur as *mut _xmlNode, 1) };
3907 io::output_buffer_close(obuf)
3908}
3909
3910#[no_mangle]
3919pub unsafe extern "C" fn htmlSaveFileFormat(
3920 filename: *const c_char,
3921 cur: *mut _xmlDoc,
3922 _encoding: *const c_char,
3923 format: c_int,
3924) -> c_int {
3925 if cur.is_null() || filename.is_null() {
3926 return -1;
3927 }
3928 let obuf = io::output_buffer_create_filename(filename, ptr::null_mut(), 0);
3929 if obuf.is_null() {
3930 return 0;
3932 }
3933 unsafe { html_serialize_to_obuf(obuf, cur as *mut _xmlNode, format) };
3934 io::output_buffer_close(obuf)
3935}
3936
3937#[no_mangle]
3946pub unsafe extern "C" fn htmlSaveFile(filename: *const c_char, cur: *mut _xmlDoc) -> c_int {
3947 unsafe { htmlSaveFileFormat(filename, cur, ptr::null(), 1) }
3948}
3949
3950#[no_mangle]
3958pub unsafe extern "C" fn htmlSaveFileEnc(
3959 filename: *const c_char,
3960 cur: *mut _xmlDoc,
3961 encoding: *const c_char,
3962) -> c_int {
3963 unsafe { htmlSaveFileFormat(filename, cur, encoding, 1) }
3964}
3965
3966#[no_mangle]
3974pub unsafe extern "C" fn htmlCtxtSetOptions(ctxt: *mut c_void, options: c_int) -> c_int {
3975 if ctxt.is_null() {
3976 return -1;
3977 }
3978 let c = ctxt as *mut HtmlOpaqueCtxt;
3979 unsafe {
3980 (*c).options = options & HTML_OPTIONS_ALL_MASK;
3981 }
3982 options & !HTML_OPTIONS_ALL_MASK & !crate::abi::types::XML_PARSE_NOENT
3983}
3984
3985#[no_mangle]
3995pub unsafe extern "C" fn htmlUTF8ToHtml(
3996 out: *mut u8,
3997 outlen: *mut c_int,
3998 input: *const u8,
3999 inlen: *mut c_int,
4000) -> c_int {
4001 const XML_ENC_ERR_INTERNAL: c_int = -1;
4003 const XML_ENC_ERR_SUCCESS: c_int = 0;
4004 const XML_ENC_ERR_SPACE: c_int = -2;
4005 unsafe {
4006 if out.is_null() || outlen.is_null() || inlen.is_null() {
4007 return XML_ENC_ERR_INTERNAL;
4008 }
4009 if input.is_null() {
4010 *outlen = 0;
4011 *inlen = 0;
4012 return XML_ENC_ERR_SUCCESS;
4013 }
4014 let mut in_pos: usize = 0;
4015 let mut out_pos: usize = 0;
4016 let in_end = *inlen as usize;
4017 let out_cap = *outlen as usize;
4018 let mut ret = XML_ENC_ERR_SPACE;
4019 while in_pos < in_end {
4020 let d = *input.add(in_pos);
4021 if d < 0x80 {
4022 if out_pos >= out_cap {
4023 break;
4024 }
4025 *out.add(out_pos) = d;
4026 out_pos += 1;
4027 in_pos += 1;
4028 continue;
4029 }
4030 let (mut c, seqlen) = if d < 0xE0 {
4031 ((d & 0x1F) as u32, 2usize)
4032 } else if d < 0xF0 {
4033 ((d & 0x0F) as u32, 3usize)
4034 } else {
4035 ((d & 0x07) as u32, 4usize)
4036 };
4037 if in_end - in_pos < seqlen {
4038 break;
4039 }
4040 for i in 1..seqlen {
4041 let dd = *input.add(in_pos + i);
4042 c = (c << 6) | ((dd & 0x3F) as u32);
4043 }
4044 let ent = htmlEntityValueLookup(c);
4045 let mut nbuf = [0u8; 16];
4046 let cp: *const u8;
4047 let mut owned_len: usize = 0;
4048 if ent.is_null() {
4049 let s = format!("#{}", c);
4050 let bytes = s.as_bytes();
4051 nbuf[..bytes.len()].copy_from_slice(bytes);
4052 cp = nbuf.as_ptr();
4053 owned_len = bytes.len();
4054 } else {
4055 cp = (*ent).name as *const u8;
4056 let mut l = 0;
4057 while *cp.add(l) != 0 {
4058 l += 1;
4059 }
4060 owned_len = l;
4061 }
4062 let len = owned_len;
4063 if out_cap - out_pos < len + 2 {
4064 break;
4065 }
4066 *out.add(out_pos) = b'&';
4067 out_pos += 1;
4068 core::ptr::copy_nonoverlapping(cp, out.add(out_pos), len);
4069 out_pos += len;
4070 *out.add(out_pos) = b';';
4071 out_pos += 1;
4072 in_pos += seqlen;
4073 }
4074 ret = out_pos as c_int;
4075 *outlen = out_pos as c_int;
4076 *inlen = in_pos as c_int;
4077 ret
4078 }
4079}